defer
执行顺序
package main
import "fmt"
func main() {
defer func() {
fmt.Println("1")
}()
defer func() {
fmt.Println("2")
}()
defer func() {
fmt.Println("3")
}()
panic("error ")
}
defer 是后进先出。panic 需要等defer 结束后才会向上传递。 出现panic恐慌时候,会先按照defer的后入先出的顺序执行,最后才会执行panic。
执行结果
3
2
1
panic: error
goroutine 1 [running]:
main.main()
函数混合
package main
import "fmt"
func calc(idx string, a, b int) int {
res := a + b
fmt.Printf("[%s] %d+%d=%d\n",idx,a,b,res)
return res
}
func main() {
a := 1
b := 2
defer calc("1", a, calc("2", a, b))
a = 0
defer calc("3", a, calc("4", a, b))
b = 1
}
执行结果
[2] 1+2=3
[4] 0+2=2
[3] 0+2=2
[1] 1+3=4
Range
for 循环是执行拷贝一个新地址 执行 ,1 不要通过这种变量值取地址 ,2不要通过这个值修改元素属性值
package main
import "fmt"
type User struct {
Id int
Name string
}
func main() {
m := make(map[string]*User)
stus :=[]User{
User{Id:1,Name:"zhang"},
User{Id:2,Name:"li"},
User{Id:3,Name:"wang"},
}
for _,stu :=range stus{
m[stu.Name] = &stu
}
for k,v :=range m{
fmt.Println(k,v)
}
}
都是使用副本的方式。所以m[stu.Name]=&stu实际上一致指向同一个指针, 最终该指针的值为遍历的最后一个struct的值拷贝。 就像想修改切片元素的属性:
package main
import "fmt"
type User struct {
Id int
Name string
}
func main() {
stus :=[]User{
User{Id:1,Name:"zhang"},
User{Id:2,Name:"li"},
User{Id:3,Name:"wang"},
}
for _,stu :=range stus{
stu.Id = stu.Id+1
}
for _,stu :=range stus{
fmt.Println(stu)
}
}
下面的打印结果还是
{1 zhang}
{2 li}
{3 wang}
闭包
闭包捕获的变量和常量是引用传递,不是值传递。
package main
import (
"sync"
"fmt"
)
func main() {
wg := sync.WaitGroup{}
wg.Add(2)
for i := 0; i < 2; i++ {
fmt.Printf("1a=%p\n", &i)
go func() {
fmt.Printf("2a=%p\n", &i)
fmt.Println("i: ", i)
wg.Done()
}()
}
wg.Wait()
}
上面程序执行结果
1a=0xc000014090
1a=0xc000014090
2a=0xc000014090
i: 2
2a=0xc000014090
i: 2
go func中i是函数参数,与外部for中的i完全是两个变量。 尾部(i)将发生值拷贝,go func内部指向值拷贝地址。引用会执行拷贝操作
package main
import (
"sync"
"fmt"
)
func main() {
wg := sync.WaitGroup{}
wg.Add(2)
for i := 0; i < 2; i++ {
fmt.Printf("1a=%p\n", &i)
go func(i int ) {
fmt.Printf("2a=%p\n", &i)
fmt.Println("i: ", i)
wg.Done()
}(i)
}
wg.Wait()
}
打印结果
1a=0xc00008e010
1a=0xc00008e010
2a=0xc00008e030
i: 1
2a=0xc000014080
i: 0
Interface
package main
import "fmt"
type People struct{}
func (p *People) foo() {
fmt.Println("people foo")
p.bar()
}
func (p *People) bar() {
fmt.Println("people bar")
}
type Student struct {
People
}
func (t *Student) bar() {
fmt.Println("student bar")
}
func main() {
t := Student{}
t.foo()
}
执行结果
people foo
people bar
package main
import (
"fmt"
)
type People interface {
Foo()
}
type Student struct{}
func (stu *Student) Foo() {
}
func newInstance() People {
var stu *Student
return stu
}
func main() {
a := newInstance()
if a == nil {
fmt.Println("empty value")
} else {
fmt.Println(a)
fmt.Printf("%p\n", a)
}
}
打印结果是
<nil>
0x0
Select
随机输出
package main
import (
"fmt"
"time"
)
func main() {
int_chan := make(chan int, 1)
string_chan := make(chan string, 1)
int_chan <- 1
string_chan <- "hello"
time.Sleep(time.Second)
select {
case value := <-int_chan:
fmt.Println(value)
case value := <-string_chan:
fmt.Println(value)
}
}
Slice
package main
import "fmt"
func main() {
s := make([]int, 3)
s = append(s, 1, 2, 3)
fmt.Println(s)
}
打印结果
[0 0 0 1 2 3]
数组
值类型
当前不会修改数组里面值的内容,修改值需要传递指针
package main
import "fmt"
func main() {
x := [3]int{1,2,3}
func(arr [3]int) {
arr[0] = 7
fmt.Println(arr) //prints [7 2 3]
}(x)
fmt.Println(x) //prints [1 2 3] (not ok if you need [7 2 3])
}
需要使用指针
func main() {
x := [3]int{1,2,3}
func(arr *[3]int) {
(*arr)[0] = 7
fmt.Println(arr) //prints &[7 2 3]
}(&x)
fmt.Println(x) //prints [7 2 3]
}
range
range 遍历包含2个值 第一个是当前的数组下标,第二个才是存储的值
func main() {
x := []string{"a","b","c"}
for v := range x {
fmt.Println(v) //prints 0, 1, 2
}
}
func main() {
x := []string{"a","b","c"}
for _, v := range x {
fmt.Println(v) //prints a, b, c
}
}
Strings
字符串修改
字符串是只读形式的字符切片 如果需要修改当前字符里面的字符 需要将字符串转换成
字符切片
x := "text"
x[0] = 'T'
fmt.Println(x)
x := "text"
xbytes := []byte(x)
xbytes[0] = 'T'
fmt.Println(string(xbytes)) //prints Text
字符串不能被赋为”空”
package main
func main() {
var x string = nil //error
if x == nil { //error
x = "default"
}
}
./hello.go:4: cannot use nil as type string in assignment
./hello.go:6: invalid operation: x == nil (mismatched types string and nil)
JSON编码
The struct fields starting with lowercase letters will not be (json, xml, gob, etc.) encoded, so when you decode the structure you’ll end up with zero values in those unexported fields.
首字母小写是无法被json 匹配的
package main
import (
"fmt"
"encoding/json"
)
type MyData struct {
One int
two string
}
func main() {
in := MyData{1,"two"}
fmt.Printf("%#v\n",in) //prints main.MyData{One:1, two:"two"}
encoded,_ := json.Marshal(in)
fmt.Println(string(encoded)) //prints {"One":1}
var out MyData
json.Unmarshal(encoded,&out)
fmt.Printf("%#v\n",out) //prints main.MyData{One:1, two:""}
}
无法下载golang.org/x/
第一种方式是使用git clone 下载GitHub的镜像地址
mkdir -p $GOPATH/src/golang.org/x/
cd !$
git clone https://github.com/golang/net.git
git clone https://github.com/golang/sys.git
git clone https://github.com/golang/tools.git
git clone https://github.com/golang/crypto.git
第二种方式推荐使用这种方式 go mod 使用 replace
replace (
golang.org/x/crypto => github.com/golang/crypto v0.0.0-20190325154230-a5d413f7728c
golang.org/x/image => github.com/golang/image v0.0.0-20190321063152-3fc05d484e9f
golang.org/x/sys => github.com/golang/sys v0.0.0-20190402142545-baf5eb976a8c
golang.org/x/text v0.3.0 => github.com/golang/text v0.3.0
)
当前现在有支持了proxy https://goproxy.io
或者命令方式
go env -w GOPROXY=https://goproxy.cn,direct