Go学习笔记(三)

一、函数

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
}

猜你喜欢

转载自blog.csdn.net/kouge94/article/details/81155714