Golang学习笔记


Golang学习笔记


前言

2022年寒假,为了学习tinyKV课程而学习Golang,就写一些东西来记录一下吧

大括号不能换行是真的难受!


package

  • package中的函数必须首字母大写才能被其他package调用
  • package可以有init函数,该函数在package被import的时候会调用

变量、数组、切片

语法

var a int = 10
var p *int = &a
a := 10
p := &a
a := [4]int {1, 2, 3, 4}
b := [...]int {2, 3, 4)
a := []int {1, 2, 3, 4)
a := [3][2]string {
{"11", "12"},
{"21", "22"},
{"31", "32"}, //The comma is necessary
}

传递参数

Go中将数组作为参数进行传递的时候执行的是值传递,这与C++不同,需要特别注意。切片可以看成是对原数组的引用,改变切片也会改变原数组。

数组赋值

数组之间可以直接赋值,但数组的类型和长度要一样,如:

a := [5]int {1, 2, 3, 4, 5}
b := [5]int {6, 7, 8, 9, 10}
a = b

数组遍历

可以用for range遍历数组和切片

a := [5]int {1, 2, 3, 4, 5}
for i, v := range a {
	//do something
}

for _, v := range a {
	//do something
}

可以用len(a)获取a数组的长度

for i := 0; i < len(a); i++ {
	fmt.Printf("%d th element is %d\n", i, a[i])
}

创建切片

slc := a[st: ed]创建数组a在[st, ed)区间的切片

a := [5]int {1, 2, 3, 4, 5}
slc := a[1:4] //从a[1]到a[4-1]的切片

用make创建切片

func make([]T,len,cap)[]T 通过传递类型,长度和容量来创建切片。容量是可选参数, 默认值为切片长度。make 函数创建一个数组,并返回引用该数组的切片。

sld := make([]int, 5, 5)
fmt.Println(sld)

追加切片元素

sld := append(sld, 123, 34) //向sld中追加两个元素

函数

语法

func name(ele1 int, ele2 string) (rtnval1 int, rtnval2 string){
	rtnval1 = 1
	rtnval2 = "asd"
	return
//
}
func main(){
	val1, val2 := name(2, "zxc")
}

可变参数函数

只有最后一个参数可以为可变参数。当传入一组数时,会转化为切片,切片名为该可变参数名。可以使用语法糖直接将切片传递给可变参数

func f(nums ...int){
	for _, v := range nums{
		fmt.Printf("%d ", v)
	}
}

func main()
{
	f(1, 2, 3, 4)
	a := []int {1, 2, 3, 4}
	f(a...)//直接传递切片,在函数中改变nums将同时改变a
}

map

语法

mp := make(map[string]int)
mp := map[string]int {
	"caution": 509,
	"joker": 717,
	"oyster": 213,
}

map[T1]T2是一个类型

var mp map[string]int
mp = make(map[string]int)//必须使用make初始化

添加、获取元素

同C++

删除元素

delete(mp, "joker")

map的长度

可用len(mp)获取

map是引用类型

当 map 被赋值为一个新变量的时候,它们指向同一个内部数据结构。因此,改变其中一个变量,就会影响到另一变量。

mp1 := map[string]int {
	"oyster": 1,
	"caution": 2,
}
mp2 := mp1
mp2["oyster"] = 3
fmt.Println(mp1) //mp1也会改变
fmt.Println(mp2) 

map作为参数进行传递的时候,也是如此。


rune

rune 是 Go 语言的内建类型,它也是 int32 的别称。在 Go 语言中,rune 表示一个代码点。代码点无论占用多少个字节,都可以用一个 rune 来表示。

func printString(s string){
	r := []rune(s)
	for i, v := range r {
		fmt.Printf("%c", v)
	}
}

结构体

语法

type E struct { //命名结构体
	s1, s2 string
	age int
}
func main(){
	e1 := E {
		s1 : "asd",
		age : 3,
		s2 : "zxc",
	}
	e2 := E{"asd", "zxc", 3}
}
func main(){
	e3 := struct{ //匿名结构体
		s1, s2 string
		age int
	}{
		s1 : "asd",
		age : 3,
		s2 : "zxc",
	}
}

指向结构体的指针

p为指向结构体的指针,则可以用p.s1代替(*p).s1

匿名字段

省略变量名,用类型名代替变量名

type Person struct {  
    string
    int
}

func main() {  
    var p1 Person
    p1.string = "naveen"
    p1.int = 50
    fmt.Println(p1)
}

提升字段

若一个结构体中有匿名结构体,则可以像访问正常成员一样访问匿名结构体的成员

导出结构体、导出字段

首字母大写才能被其他包使用


方法

方法类似于类的成员函数

语法

func (e E) show(tms int) {
	for i := 0; i < tms; i++ {
		fmt.Println(e)
	}
}

func main(){
	e := E { "asd", "zxc", 3 }
	e.show(3)
}

为了在一个类型上定义一个方法,方法的接收器类型定义和方法的定义应该在同一个包中。

指针接收器

使用指针接收器可以改变e的内容。当使用指针接收器时,e.show()(&e).show()都是合法的