Learning Go - 3 more types

1. 指针

与C语言相同,只是没有指针运算(如*void随意转换指针类型)

2. 结构体

type Vertex struct {  // 定义结构体 为一种新类型
	X int
	Y int
}
func main() {
	v := Vertex{1, 2}  // 这样用
	v.X = 4
	fmt.Println(v.X)  // 4
	p := &v
	p.X = 1e9  // (*p).X = 1e9 结构体指针,两种写法都对
	fmt.Println(v)

	v2 = Vertex{X: 1}  // 默认值Y:0
	fmt.Println(v2)  // 1, 0
}

3. 数组

var a [2]string  // 数组定义 var a[2] string 空格随意
a[0] = "Hello"
a[1] = "World"  // 也可以这样写 a := [...]string{"Hello", "World"}
fmt.Println(a)  // [Hello World]

4. slice

对底层数组Array的封装, 指针指向同一片数组空间,和数组不同的是切片并没有给定固定的长度。

s := []int{2, 3, 5, 7, 11, 13}
s[1:4] == [3 5 7]  // 切片,同python:包含前端,不包含后端
b := make([]int, 0, 5) // len(b)=0, cap(b)=5

var z []int  // z == nil
fmt.Println(z, len(z), cap(z))  // [] 0 0

a = append(a, 2, 3, 4)  // 如果超出cap,则指向重新copy的大数组
b := []int{1, 2, 3}
a = append(a, b...)  // ...语法 == "append(a, b[0], b[1], b[2])"

read more

5. range 函数

对 slice 或者 map 进行迭代循环

var pow = []int{1, 2, 4, 8, 16, 32, 64, 128}
for i, v := range pow {  // index and value
	fmt.Printf("2**%d = %d\n", i, v)
}
for i := range pow  // only index
for _, value := range pow  // only value

exercise-slice: 将整数转换为灰度图片进行展示

func Pic(dx, dy int) [][]uint8 {
	ret := make([][]uint8, dy)  // 初始化二维数组 y * x
	for i := range ret {  // range y
		ret[i] = make([]uint8, dx)  // 初始化里边的一维元素!
		for j := range ret[i] {  // range x
			ret[i][j] = uint8(i^j)  // uint8 类型转换
		}
	}
	return ret
}

6. map

type Vertex struct {
	Lat, Long float64
}
var m = map [string] Vertex{  // 这样定义
	"Bell Labs": Vertex{
		40.68433, -74.39967,
	},
	"Google": {37.42202, -122.08408},  // 可以省略
}
example:
func main() {
	m := make(map[string]int)  // map在使用之前必须用make而不是new来创建;值为nil的map是空的,并且不能赋值。

	m["Answer"] = 42  // 插入 or 修改
	fmt.Println("The value:", m["Answer"])

	delete(m, "Answer")  // 删除
	fmt.Println("The value:", m["Answer"])

	v, ok := m["Answer"]  // 判断:如key在m中,ok为true。否则ok为 false并且elem是map的元素类型的零值。
	fmt.Println("The value:", v, "Present?", ok)
}
m = make(map[string]Vertex)

exercise-map: wordcount

func WordCount(s string) map[string]int {
	res := make(map [string]int)
	for _,v := range strings.Fields(s) {  // Fields函数,类似Python的Split
		res[v]++
	}
	return res
}

7. 函数值

函数可以作为值赋给变量,类似函数式编程的匿名函数

hypot := func(x, y float64) float64 {  	//无名函数赋值给变量hypot
	return math.Sqrt(x*x + y*y)
}
fmt.Println(hypot(3, 4))  // 5

函数闭包:对象是附有行为的数据,而闭包是附有数据的行为

func adder() func(int) int {  // 函数 adder 返回一个闭包,每个返回的闭包都被绑定到其各自的 sum 变量上
	sum := 0
	return func(x int) int {
		sum += x
		return sum
	}
}
func main() {
	pos, neg := adder(), adder()  // 函数被“绑定”在变量上,变量就好像函数指针
	for i := 0; i < 10; i++ {
		fmt.Println(
			pos(i),  // 0 1 3 6 10...
			neg(-2*i),  // 这2者结果是隔离的,每次调用adder返回的函数都将生成并保存一个新的局部变量sum
		)
	}
}

8. 闭包实例 - fibonacci

func fibonacci() func() int {
	num1, num2 := 0, 1
	return func() int {
		tmp := num2
		num2 += num1
		num1 = tmp
		return num2
	}
}
func main() {
	f := fibonacci()
	for i := 0; i < 10; i++ {
		fmt.Println(f())  // 1 2 3 5 8 13 21 34 55 89
	}
}
Loading Disqus comments...
Table of Contents