# go 语言学习
go 的初始化方式,要么用
a :=
or var a =
# 切片
注意切片
b := a[1:2] | |
fmt.Println(&b[0], &a[1]) |
结果:
拥有相同的地址空间,也就是说,切片实际上只是一个引用。
var s2 = make([]int, 2) | |
fmt.Printf("s2: %v\n", s2) | |
s2 = append(s2, 1, 2, 3) | |
fmt.Printf("s2: %v\n", s2) | |
fmt.Println(len(s2)) |
即使用 make 指定了切片的大小,它也可以扩容。
要从切片 a 中删除索引为 index
的元素,操作方法是 a = append(a[:index], a[index+1:]...)
用 copy
作为切片的拷贝,如果直接用 =
则是引用。
# Map
初始化:
aMap := make(map[keyType]valueType, cap)
cap
只是预设的大小,mao 是可以动态增长的,这和 C 语言很类似。
aMap := make(map[int]*[]int) | |
tmp := []int{1, 2, 3} | |
aMap[0] = &tmp | |
fmt.Printf("aMap: %v\n", aMap) | |
tmp01 := *aMap[0] | |
for k, v := range tmp01{ | |
fmt.Println("") | |
} |
aMap := make (map [int]*[] int) : 设置 map 的值类型为切片指针
aMap := make (map [int][] int): 设置 map 的值类型为切片
# 判断是否有键
t, ok := my["address"] | |
if ok{ | |
fmt.Printf("t: %v\n", t) | |
} |
t, ok := my["address"]
用这个方式
# 闭包
闭包就是函数加引用环境。
add 函数返回的就是一个函数,但是这个返回的函数会引用外部的变量 x。
也就是说 f
在其生命周期中,x 会一直存在。
输出:
闭包其实并不复杂,只要牢记 闭包=函数+引用环境
。
# 递归
尾递归求解斐波拉切数列
package main | |
import "fmt" | |
func fab(n, n1, n2 int) int { | |
if n == 0 { | |
return n1 | |
} | |
return fab(n-1, n1+n2, n1) | |
} | |
func main() { | |
fmt.Println(fab(10, 1, 0)) | |
} |
# Init
go 中有特殊的函数: init
函数,它会在执行 main
函数之前自动执行。
func main() { | |
fmt.Println(fab(10, 1, 0)) | |
} | |
func init(){ | |
fmt.Println("init.....") | |
} |
结果:
会先于 main 函数自动执行,并且一个源文件中可以有多个 init 函数。
# 类型定义和类型别名
类型定义:
type NewType Type
类型别名:
type NewType = Type
# 结构体
未初始化的结构体,成员都是零值 int 0 float 0.0 bool false string nil nil
初始化方式有列表初始化和部分初始化,可以看 golang 结构体的初始化
struct
可以用 new
来初始化:
pb := new(Book)
pb
是实例化的 Book 结构。
# 接口
这个接口有点搞。。。
首先,接口定义:
type Shape interface { | |
Area() float32 | |
} |
接口中定义方法类型。
结构体需要实现接口
type Square struct { | |
sideLen float32 | |
} | |
type Triangle struct { | |
Bottom float32 | |
Height float32 | |
} | |
type Shape interface { | |
Area() float32 | |
} | |
func (s Square) Area() float32{ | |
return s.sideLen * s.sideLen | |
} | |
func (t Triangle) Area() float32{ | |
return t.Bottom*t.Height/2 | |
} |
可以看到针对正方形和三角形分别实现了 Area 函数。
# 接口的使用:
t := Triangle{1, 2} | |
s := Square{4} | |
shapes := []Shape{t, s} | |
for _, shape:= range shapes{ | |
fmt.Printf("shape.Area(): %v\n", shape.Area()) | |
} | |
var sh Shape | |
sh = t | |
fmt.Printf("sh.Area(): %v\n", sh.Area()) | |
sh = s | |
fmt.Printf("sh.Area(): %v\n", sh.Area()) |
也可以用结构体的指针来对接口进行赋值。
# 嵌套接口
package main | |
import "fmt" | |
type Fly interface { | |
fly() | |
} | |
type Swim interface { | |
swim() | |
} | |
type FlyFish interface { | |
Fly | |
Swim | |
} | |
type fish struct { | |
} | |
func (f fish) fly() { | |
fmt.Println("flying") | |
} | |
func (f fish) swim() { | |
fmt.Println("swimming") | |
} | |
func main() { | |
var flyfish FlyFish | |
flyfish = fish{} | |
flyfish.fly() | |
flyfish.swim() | |
} |
FlyFish
是一个嵌套接口,它实现了 Fly 和 Swim 两个接口,但实际上只要把嵌套接口中所有方法都实现就可以了。
# 继承
package main | |
import "fmt" | |
type Animal struct { | |
name string | |
age int | |
} | |
func (animal Animal) eat() { | |
fmt.Println("eat...") | |
} | |
func (animal Animal) sleep() { | |
fmt.Println("sleep...") | |
} | |
type Dog struct { | |
Animal | |
color string | |
} | |
type Cat struct { | |
Animal | |
color string | |
} | |
func main() { | |
dog := Dog{ | |
Animal{"huahua",16}, | |
"red", | |
} | |
dog.eat() | |
dog.sleep() | |
cat := Cat{ | |
Animal{"yuanyuan", 1}, | |
"black", | |
} | |
cat.sleep() | |
cat.eat() | |
} |
# 反射
package main | |
import ( | |
"fmt" | |
"reflect" | |
) | |
func main() { | |
// utils.Test() | |
type MyInt int | |
var x MyInt = 6 | |
z := reflect.TypeOf(x) | |
v := reflect.ValueOf(x) | |
// fmt.Printf("%v", z) | |
fmt.Println(v.Kind()) | |
fmt.Println(z.Kind()) | |
fmt.Println(z) | |
fmt.Println(v) | |
var a interface{} | |
t := "hello" | |
a = t | |
value, ok := a.(string) | |
if ok{ | |
fmt.Println("can convert") | |
fmt.Println(string(value)) | |
}else{ | |
fmt.Println("cant do convert") | |
} | |
va, ok := a.(float32) | |
if ok{ | |
fmt.Println(va) | |
}else{ | |
fmt.Println("not float32") | |
} | |
} |