golang基础重点摘要

 nadia     2021-05-11     1318     0   

欢迎来到银盒子的世界~

go基础

声明变量

eg:

name := "name"

age := 1

result := false

变量声明的零值,也就是默认值,eg:

var a int

var b float64

var c bool

var d string

输出是  0   ""   false   0

数组和切片

数组可以这样声明

array := [...]int{1,2,3}

切片可以这样声明

slice := []int{1,2.3}

一般遍历的时候,都用切片遍历,切片可以用append往后边追加元素,eg:

slice2 := append(slice,"f","d"),追加后的切片,指向了一个新的变量名slice2

make函数

make函数只能用在切片(slice) 映射/也就是字典(map)和chan的初始化上

字面量

常用的3中字面量

1,表示基础数据类型的值的各种字面量

2,构造各种自定义的复合函数类型的类型字面量

3,用来够着类型struct(结构体)、Array(数组)、Slice(切片)和Map(字典)的值,一般由值的字面量类型加大括号组合起来符合使用,eg:

nameAgeMap := map[string]int{"飞雪无情":20}  // 这是字典,又叫映射

slice := []int{1,2.3} // 切片

array := [...]int{1,2,3}  // 数组

遍历

遍历都是用for range  ,eg:

数组遍历 for i,v := range array{}  i是下标,也就是索引,v是具体的值

字典遍历 for k,v := range map{}   k是kay,v是value

字符串遍历 for i,r := range string{} 这里需要注意,如果是汉字,会被当成unicode编码的,一盒汉字当成3个长度遍历的

字符串长度

如果直接用len(string)来算字符串的长度,一个汉字会对应三个字节,等于长度会被*3

要想用一个汉字当一个长度,用utf8.RuneCountlnString,eg:

fmt.Println(utf8.RuneCountlnString(String))

函数

比较常见的函数结构如下:

func sun(a,b,params ...int) (result,err) {}

func 是函数固定开头

sun是函数名字(小写就是私有函数)

紧挨着sun的括号里,是函数的参数,a和b 是定长参数,一个萝卜一个坑,params ...int  这种写法就是变长参数,可以传多个参数

最后一个括号里是函数的返回,在函数定义的时候就写好要返回的结果,下边函数结束时,可以只写一个return就可

函数的公有私有

函数名字大写,如Pringln就是共有函数,可以跨包调用,函数名字小写如sum,就是私有的函数

闭包

函数嵌套,在外边一个正常定义的函数里,可以再定义一个匿名函数,这个匿名函数还能用外部函数的参数,这就是闭包。eg:

func colsure() func() int {

i  := 0

return func() int {

i++

return i

}

}

上边这个例子,匿名函数既可以作为外部函数colsure,在定义函数的时候填写的返回值,也可以在函数内部,用return返回,这种就是流式编程,把函数作为另外一个函数的参数。

方法

方法的声明,eg:

type Age int

func (a Age) String(){

	fmt.Pringln("年龄是:",a)

}

String()就是类型是Age的方法,类型Age就是方法 String()的接受者,但是这接受者,都要用小括号圈起来,小括号里,第一个是变量名,第二个是具体的接受者。所以func 后边紧跟着的第一个括号里的(a Age),就是方法String()的接受者,下边说方法的接受者,指的就是(a Age)

方法的调用,下边的代码示例省略了main()函数

age := Age(25)

age.String()

注意,给方法传参数,得放到类型Age里,然后,赋值给变量age,这样age直接点String(),蚕食就直接通过接受者里的变量名a,拿到了,然后就执行了方法里的代码。

值类型接受者和指针类型接受者。

type Age int
func (a Age) Strings() {
   fmt.Println("SDSD",a)
}
func (a *Age) String() {
   *a = Age(30)
}

然后在main()函数里调用方法

age := Age(25)
age.Strings()
age.String()
age.Strings()

然后就发现输出第一行是25,第二行就变成了30

几个点

1,一个Age类型可以有多个方法,比如Strings()和String()

2,在方法String()中,接受体(a *Age),是把指针标志落到类型本体上

3,在main()函数里,调用方法的时候,除了可以使用值类型变量,还可以使用指针类型变量,eg:(&a).String()。

age := Age(25)
age.Strings()
(&age).String()
age.Strings()

4,用点可以点出方法名

5,在调用方法的时候,指针类型的就得用&符号,eg:   (&age).String()

6,声明方法的时候,接受体里的指针是落到类型本体,但是方法里边用这个指针,得落到那个变量名上,eg:

func (a *Age) String() {
   *a = Age(30)
}

 

方法表达式

方法直接赋值给一个变量,就是方法表达式

声明一个结构体

type person struct {

name string

age uint

}

在结构体中,name和age被称为成员名/字段名。结构体里边可为空

实例化一个结构体

eg:    p := person{age:30}

访问一个结构体的字段和调用一个类型的方法(调用一个类型的方法,意思就是方法上边得跟着一个type Age int,意思就是得提前指定这个方法的类型,所以才会说,调用一个类型的方法)一样都是点。还是用上边的例子,eg:

结构体,p.age

方法

 

接口

要实现一个接口,必须实现这个接口提供的所有方法,而接口是实现者必须是一个具体的类型,比如接口体。eg:

// 声明一个结构体
type age struct {
   name string
   sex int
   ass adress
}
// 声明结构体age 里边的嵌套结构体adress
type adress struct {
   add string
   mobile int
}

// 定义一个接口Stringers,里边有个方法String()
type Stringers interface {
   String() (string,int)
}

// 上边接口里,调用的那个方法String(),返回的是字符串,注意方法和函数的区别,就是方法前边有个(a,age),
// 反应过来方法和函数的区别的了,在函数前边加上方法特有的(a age),就类似于css起了一个类名,然后都是div标签,
// 用结构体age实现接口Stringers
func (a age) String() (string,int) {
   return fmt.Sprintf("sex是:%d,名字是:%s",a.sex,a.name),a.sex
}

// 再用结构体ass实现接口Stringers
func (add adress) String() (string,int){
   return fmt.Sprintf("手机号是:%d,地址是:%s",add.mobile,add.add),add.mobile
}

// 再声明一个函数,打印上边的接口Stringers,这个函数只有参数s,没有返回值
func printStrings(s Stringers) {
   fmt.Println(s.String())
}

最后再在main()函数里调用函数printStriger,传参数

func main() {
   a := age{name: "sad",sex: 12,ass:adress{add: "ssd",mobile: 1212121212}}  //这是初始化一个结构体age,用的是结构体字面量的方式初始化的,没有初始化到的值,是空,然后把初始化出的结构体,赋值给一个变量,也就是a
   //fmt.Println(a.ass.mobile)
   printStrings(a)  // 函数printStrings,在这里调用,参数是定长的变量a.补充,变长的参数是这样params ...int,放到参数的最后边,注意,函数里,处理这里变长的参数params,一般是用for range 遍历出来的
   printStrings(a.ass)  // 因为结构体age,里边有嵌套的ass,所以可以直接这样点出来
   //有个疑问,为什么这里调用函数里传的参数是变量a,这个a其实就是一个初始化的结构体,但是下边函数里接受的参数,是接口Stringers
   //反应过来了,调用的地方,先把变量a传进去,然后声明函数的地方,参数是Stringers,所以参数a其实被传进来到接口Stringers中了
   //然后接口Stringers中,调用了方法String,并规定了返回的参数是两个,一个是字符串,一个是数字
   //然后下边有两个方法,然后这俩方法的方法名一样,但是接受者不一样,因为定义了两个结构体,所以这两个机构体都作为接口的实现者去实现这个接口的方法,就都可以被实现了。一个接口,调用一个方法名,然后对应的接受者不同的方法就都被实现了
}
值接受者和指针接受者

直接写结论,还是用上边那个例子里的。(方法接受者就是方法前边第一个括号里的)eg:

1,当用值类型的方法接受者时:func (a age) String() (string,int) {},下边的实现接口的类型,有两种选择:

1)printStrings(a)   // 接口体类型的实现接口的类型

2)printStrings(&a)  // 指针类型的实现接口的类型

2,当用指针类型的方法接受者时:func (a *age) String() (string,int) {},下边的实现接口的类型,只有一种选择:

1)printStrings(&a) // 指针类型的实现接口的类型

发表评论