go的环境配置级运行命令
goroot: go 的sdk运行路径
gopath: go的工作环境,配有src pkg bin 三个子文件
gobin: 工作区的生产的main包的运行文件exe存放路径,main包为执行入口文件
go的常见命令
go install:主要用来生成库和工具。一是编译包文件(无main包),将编译后的包文件放到 pkg 目录下($GOPATH/pkg
)。二是编译生成可执行文件(有main包),将可执行文件放到 bin 目录($GOPATH/bin
)
go build: 用于测试编译包,在项目目录下生成可执行文件(有main包)
go get [main.go]:
参数[main.go所在路径]:可选。相对GOPATH/src路径。 缺省是.(src自己)。可指定src下面的子文件夹路径。
go get会做2件事:1. 从远程下载需要用到的包。2.执行go install。
go语言值传递和指针传递
不同与java,go中引入了指针,在java中通过对象的引用(对象的堆内存中第一个内存的别名)来使用,复制和函数传参都是值传递,而go对象创建采用的struct来创传递可以使用T(值传递)或者*T(指针传递)传递。
- 使用T传递参数或者赋值时,不可以理解成深拷贝,只是值类型或者指针类型的复制,例如slice、map的赋值等也是值传递slice、map以及chanel这三种类型都是指向指针类型(*T),指向一个底层的数据结构,传递时时传递指针指向的内存值。
- 值传递修改不会影响,而指针传递修改会影响原值
- for-range循环也是将元素的副本赋值给循环变量,所以变量得到的是集合元素的副本,循环变量是重用的,所以副本地址相同
- 如果变量是一个大的struct或者数组,则副本的创建相对会影响性能,这个时候考虑使用*T,只创建新的指针,
- 如果定义成
T
,Go编译器尽量将对象分配到栈上,而*T
很可能会分配到对象上,这对垃圾回收会有影响 -
package main import "fmt" type Bird struct { Age int Name string Hobbies []string } var parrot1 = Bird{Age: 1, Name: "Blue", Hobbies: []string{"ball1", "swim", "book"}} func main() { fmt.Printf("parrot1:\t\t %+v, \t\t内存地址:%p\n", parrot1, &parrot1) //slice 为指针类型 s := []Bird{parrot1} s = append(s, parrot1) parrot1.Age = 3 parrot1.Hobbies[0] = "basketball" fmt.Printf("parrot2:\t\t %+v, \t\t内存地址:%p\n", s[0], &(s[0])) fmt.Printf("parrot3:\t\t %+v, \t\t内存地址:%p\n", s[1], &(s[1])) } //指针类型赋值结果 parrot1: {Age:1 Name:Blue Hobbies:[ball1 swim book]}, 内存地址:0x5640c0 parrot2: {Age:1 Name:Blue Hobbies:[basketball swim book]}, 内存地址:0xc210048060 parrot3: {Age:1 Name:Blue Hobbies:[basketball swim book]}, 内存地址:0xc210048090 //当讲Hobbies改成array类型时,数组类型赋值结果 parrot1: {Age:1 Name:Blue Hobbies:[ball1 swim book]}, 内存地址:0x527da0 parrot2: {Age:1 Name:Blue Hobbies:[ball1 swim book]}, 内存地址:0xc420010120 parrot3: {Age:1 Name:Blue Hobbies:[ball1 swim book]}, 内存地址:0xc420010168