go-learn基础04 struct,slice,map

76 阅读4分钟

指针

Go里的指针保存了值的内存地址, *T指向的是T类型的指针, 零值为nil

var p *string ,&操作符会生成一个指向变量的指针

a := 2
c = &a

*操作符用来指向指针的底层值, go没有指针运算.

package main

import "fmt"

func main() {
	a, b := 2, 3
	c := &a         // 指向a
	fmt.Println(*c) //读取指针c的值 : 2
	*c = 22
	fmt.Println(a) //查看a的值: 22

	c = &b
	*c = *c + 1
	fmt.Println(b) // 4
}

结构体

结构体是一组字段, 可以用点来访问字段

package main

import "fmt"

type Person struct {
	name string
	age  int
}

func main() {
	person := Person{"zhangsan", 22}
	fmt.Println(person)      //{zhangsan 22}
	fmt.Println(person.name) //zhangsan
	p1 := Person{name: "lisi"} // 可以指定某个字段,其他字段为零值
	p2 := Person{}
	p3 := &Person{"mazi", 33} // &返回指针
	fmt.Println(p1, p2, p3)  //{lisi 0} { 0} &{mazi 33}
}

数组

类型[x]T表示有x个T类型的值的数组, var arr [3]int声明了有3个整数的数组, 数组不能改变大小.

package main

import "fmt"

func main() {
	var arr [3]int
	arr[0] = 1
	arr[1] = 2
	arr[2] = 3
	fmt.Println(arr) //[1 2 3]
	arr1 := [3]int{1, 2, 3}
	fmt.Println(arr1) // [1 2 3]
}

切片

数组的大小是固定的,但是切片可以为数组提供动态的大小,更加常用, []T表示元素类型为T的切片,通过2个下标来取值,比如 arr[1:3],包含了arr的下标1-2的元素.

package main

import "fmt"

func main() {
	arr := [5]int{1, 2, 3, 4, 5}
	s := arr[1:3]
	fmt.Println(s) // [2 3]
	s[0] = 22
	fmt.Println(arr)                         //[1 22 3 4 5]  切片的改变会引起原数组的改变
	s1 := []int{1, 2, 3}                     //会直接构建一个引用数组的切片
	fmt.Println(s1)                          // [1 2 3]
	fmt.Printf("the type of s1 is %T\n", s1) //the type of s1 is []int
	s2 := arr[:]                             // 下边界默认是0, 上边界是数组的长度, 可以省略
	s3 := arr[:5]
	fmt.Println(s2, s3) //[1 22 3 4 5] [1 22 3 4 5]
}

切片的容量和长度

  1. 切片的长度是包含的元素个数.

  2. 切片的容量是第一个元素开始到底层数组末尾的个数.

  3. 长度和容量用len(s)和cap(s)获取.

package main

import "fmt"

func main() {
	s := []int{1, 2, 3, 4, 5, 6}
	fmt.Println(s, len(s), cap(s)) //[1 2 3 4 5 6] 6 6
	s = s[:2]
	fmt.Println(s, len(s), cap(s)) //[1 2] 2 6
	s = s[:4]
	fmt.Println(s, len(s), cap(s)) //[1 2 3 4] 4 6
	s = s[2:]
	fmt.Println(s, len(s), cap(s)) //[3 4] 2 4
}

切片的零值是nil, 没有底层数组

make创建切片

切片可以用make函数创建. make接收的参数是t Type, size ...IntegerType.

package main

import "fmt"

func main() {
	a := make([]int, 0, 3)         // 第二个参数指定长度,
	fmt.Println(a, len(a), cap(a)) //[] 0 3
	b := make([]int, 2)
	fmt.Println(b, len(b), cap(b)) //[0 0] 2 2

	c := [][]int{[]int{1, 2, 3}, []int{4, 5, 6}} // 切片里可以包含切片, 可以是任何类型
	fmt.Println(c, c[1][1])
}

追加元素

使用append内建函数追加元素, 第一个参数为slice, 后面可以添加多个元素, s的底层数组太小是,会自动分配一个更大的数组.

package main

import "fmt"

func main() {
	var s []int
	s = append(s, 1)
	fmt.Println(s, len(s), cap(s)) //[1] 1 1
	s = append(s, 2, 3, 4, 5)
	fmt.Println(s, len(s), cap(s)) //[1 2 3 4 5] 5 6
}

遍历

package main

import "fmt"

func main() {
	s := make([]int, 5)
	for i := range s {
		s[i] = i
	}
	fmt.Println(s)
	for _, v := range s { // i, v 可以用_忽略, 如果不需要某个变量
		fmt.Println(v)
	}
}

映射

map相当于python中的dict, 也可以用make函数初始化.

初始化

package main

import "fmt"

type Person struct {
	name string
	age  int
}

var m map[string]Person

func main() {
	m = make(map[string]Person)
	m["张三"] = Person{"张三", 22}
	m["bob"] = Person{"bob", 32}
	fmt.Println(m["张三"])
	fmt.Println(m) //map[bob:{bob 32} 张三:{张三 22}]

	// 可以省略类型名
	m1 := map[string]Person{
		"tom":   {"tom", 22},
		"danny": {"danny", 32},
	}
	fmt.Println(m1) //map[danny:{danny 32} tom:{tom 22}]
}

修改map

元素不存在返回的是元素类型的零值,ok为false.

package main

import "fmt"

func main() {
	m := make(map[string]int)
	m["bob"] = 22
	m["danny"] = 32
	fmt.Println("bob", m["bob"])
	delete(m, "bob") // 删除元素
	v, ok := m["bob"]
	fmt.Println(v, ok) //0 false 
	v, ok = m["danny"]
	fmt.Println(v, ok) //32 true
}

闭包

package main

import "fmt"

// 闭包
func fib() func() int {
	a, b := 0, 1
	return func() int {
		tmp := a
		a, b = b, a+b
		return tmp
	}
}

func main() {
	f := fib()
	for i := 0; i < 10; i++ {
		fmt.Println(f())
	}
}


学习更多Golang知识

不负春光 不负自己

戳“更多知识”我们一起进步