一、函数
package main
import (
"fmt"
"math"
"reflect"
"runtime"
)
// 使用apply调用op函数,参数是a,b
func apply(op func(int, int) int, a, b int) int {
// 通过反射得到指向函数的指针,通过运行时函数获取指针指向函数的名字
p := reflect.ValueOf(op).Pointer()
opName := runtime.FuncForPC(p).Name()
fmt.Printf("Calling function %s with args "+
"(%d, %d)\n", opName, a, b)
return op(a, b)
}
// 可变参数列表
func sum(numbers ...int) int {
s := 0
for i := range numbers {
s += numbers[i]
}
return s
}
// 返回值中error是对象
func eval(a, b int, op string) (int,error){
switch op{
case "+":
return a + b, nil
case "-":
return a - b, nil
case "*":
return a * b, nil
case "/":
// 第二个返回值不存
q, _ := div(a, b)
return q, nil
default:
return 0, fmt.Errorf("unsupported operation: %s", op)
}
}
// 函数中可以直接给q, r赋值,然后return即可,
// 但函数过长时,不便寻找,因此建议如下写法
func div(a, b int) (q, r int) {
return a / b, a % b
}
func main() {
fmt.Println("Error handling")
if result, err := eval(3, 4, "x"); err != nil {
fmt.Println("Error:", err)
} else {
fmt.Println(result)
}
q, r := div(13, 3)
fmt.Printf("13 div 3 is %d mod %d\n", q, r)
// 调用自定义函数
fmt.Println("pow(3, 4) is:", apply(
func(a int, b int) int {
return int(math.Pow(
float64(a), float64(b)))
}, 3, 4))
fmt.Println("1+2+...+5 =", sum(1, 2, 3, 4, 5))
}
二、指针
package main
import (
"fmt"
)
func swap(a, b int) (int, int) {
return b, a
}
func swap2(a, b *int){
*a, *b = *b, *a
}
func main() {
a, b := 3, 4
c, d := 5, 6
a, b = swap(a, b)
fmt.Println("a, b after swap is:", a, b)
// 传入变量地址
swap2(&c, &d)
fmt.Println("c, d after swap is:", c, d)
}
三、数组
package main
import (
"fmt"
)
// 这里的参数是一个长度为5的数组,[]int代表切片,下文中会提及
func printArray(arr [5]int){
// go中数组是值传递,这里修改数组的第一个元素
// 打印出的数据发生修改,但是原数据不修改
arr[0] = 1000
// range返回索引序号和值,也可以只返回索引
for i, v := range arr {
fmt.Println(i,v)
}
}
func main() {
// 默认5个0
var arr1 [5]int
// 其余为补0
arr2 := [5]int{1,3,5}
// 自适应长度
arr3 := [...]int{2,4,6,8,10}
var grid [3][4]int
fmt.Println(arr1,arr2,arr3)
fmt.Println(grid)
printArray(arr1)
printArray(arr3)
fmt.Println(arr1, arr3)
}
四、切片
package main
import (
"fmt"
)
func updateSlice(a []int){
a[0] = -1
}
func main() {
// slice本身是没有数据的,是对底层array的一个view
arr := [...]int{0,1,2,3,4,5,6,7}
fmt.Println("arr[2:6]", arr[2:6]) //[2 3 4 5]
fmt.Println("arr[:6]", arr[:6]) //[0 1 2 3 4 5]
fmt.Println("arr[2:]", arr[2:]) //[2 3 4 5 6 7]
fmt.Println("arr[:]", arr[:]) //[0 1 2 3 4 5 6 7]
// 更改slice,影响全局
updateSlice(arr[2:6])
fmt.Println("arr[2:6]", arr[2:6]) //[-1 3 4 5]
fmt.Println("arr", arr) //[0 1 -1 3 4 5 6 7]
// reslice
arr1 := arr[:]
arr1 = arr1[:6]
fmt.Println(arr1) // [0 1 -1 3 4 5]
arr1 = arr1[2:]
fmt.Println(arr1) // [-1 3 4 5]
// slice的扩展,原理见下图Slice的扩展和实现
s1 := arr[2:6] // [-1 3 4 5]
s2 := s1[3:5] // [5 6]
fmt.Println(s1,s2)
}
slice由三部分组成,ptr是指向第一个元素的指针;len是slice的长度,使用arr[x]取值时,0<=x<=len-1,否则越界错误;cap是从ptr开始整个slice的长度,因此,slice可以向后扩展,但是不超过cap的最大长度cap(arr)即可
slice添加元素
package main
import (
"fmt"
)
func main() {
arr := [...]int{0,1,2,3,4,5,6,7}
fmt.Println(arr, len(arr), cap(arr)) //[0 1 2 3 4 5 6 7] 8 8
s1 := arr[2:6]
fmt.Println(s1, len(s1), cap(s1)) //[2 3 4 5] 4 6
s2 := s1[3:5]
fmt.Println(s2, len(s2), cap(s2)) //[5 6] 2 3
// 给s2添加新元素10,覆盖原来的元素7
s3 := append(s2, 10)
fmt.Println(s3, len(s3), cap(s3)) //[5 6 10] 3 3
fmt.Println(arr, len(arr), cap(arr)) //[0 1 2 3 4 5 6 10] 8 8
// s4,s5由于超过原cap数组的大小,系统会自动给分配一个新的更大底层数组
// 并且复制原数组元素值到新数组,原数组如果没有其他调用,被垃圾回收
s4 := append(s3, 11)
fmt.Println(s4, len(s4), cap(s4)) //[5 6 10 11] 4 8
s5 := append(s4, 12)
fmt.Println(s5, len(s5), cap(s5)) //[5 6 10 11 12] 5 8
// 当继续添加元素,cap长度达到8时,会创建一个长度为16的数组,以2倍数递增,以此类推
}
创建/复制/删除slice
package main
import (
"fmt"
)
func print(a []int){
fmt.Println("len:",len(a),"cap:",cap(a))
}
func main() {
var s []int
for i:=0;i<100;i++ {
s = append(s, 2*i+1)
}
s1 := []int{2,4,6,8}
// len: 4 cap: 4
print(s1)
s2 := make([]int, 16)
// len: 16 cap: 16
print(s2)
s3 := make([]int, 10, 32)
// len: 10 cap: 32
print(s3)
copy(s2, s1)
s1[0] = -1
fmt.Println(s1) //[-1 4 6 8]
fmt.Println(s2) //[2 4 6 8 0 0 0 0 0 0 0 0 0 0 0 0]
// append第二个参数是可变参数,加...表示s2从第4个参数开始后面所有
s2 = append(s2[:3], s2[4:]...)
fmt.Println(s2) //[2 4 6 0 0 0 0 0 0 0 0 0 0 0 0]
print(s2) //len: 15 cap: 16
}