Go语言基础(二)| 青训营笔记

170 阅读8分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第三篇笔记

看到这的朋友们,如果没有看过我写的Go语言基础(一)的话会很懵,建议看一下 Go语言基础(一)

Go语言基础(二)

复杂数据类型

上次学到了数组,这里我开始学习切片,切片作为Go最特殊的一种数据类型,是我们必须需要掌握的。
切片室对底层数组一个连续片段的引用(该数组称为相关数组,通常是匿名的),所以,切片是一个引用数据类型。
切片类型表示其元素类型的所有数组切片的集合。
未初始化切片的值为nil

对于nil值的理解

其实刚开始看到这个值的时候,我首先想到的是Java中的null值,但是其实是不相同的。

在go中,非指针类型的对象是不能赋值为nil的

    var b []int
    if b == nil{
            fmt.Println("b的值为nil")
    }//b的值为nil

并且非指针类型的对象也不能和nil判断,会报编译错误

    b := 123
    if b == nil{
            fmt.Print("b的值为nil")
    }//cannot convert nil to type int

切片(slice)

我们先来说说切片,切片有长度,有容量且容量>=长度

在Go中有三种定义切片的方法:

  1. 其实数组就是一种特殊的切片,只不过这时候容量是等于长度的
a := []int{1,2,3,5,4}//看起来我们定义了一个数组a,其实他也是一个切片
  1. 使用make()函数来创建一个切片
b := make([]int,3,10)//切片c的长度为3,容量为10
//var slice = make([]type,length,capacity)
  1. 从数组或者切片中生成一个新的切片
var c = a[1:3:5]
//这个切片c就是切片a的一部分,只不过,容量为5,从a[1]开始到a[3]结束
//var new = old[low:high:max],这里的长度为high-low,容量为max-low
//这里的low-high 注意,是左闭右开的
//注意切片取值时,索引值大于长度会导致异常发生
//假如这里我写了一段代码:d := c[2] 这样就会导致越界

也可以利用append()或copy()来创建切片,不过这种方式是在原切片的基础上实现的!

字典(map)

在Java中我们知道,Map是一个k-v键值对,同样的,Go中也是一样的,map也是k-v键值对,都是无序的(无论是k还是v,如果想给他们排序,可以将k或者v放入切片中,然后通过排序方法给切片排序)

关于map的初始化:

  1. 使用make()函数
    maps := make(map[string]int,100)
    //这里定义了一个map,k的类型为string,v的类型为int,容量为100
    //make(map[keyType]valueType)
  1. 直接定义
    var a = map[string]int{}
    //定义了一个map a 里面没有内容
    var b = map[string]int{"1":1,"2",2}
    //定义了一个map b 里面有内容
    var c map[string]int 
    //c是一个nil,注意往c中放值的时候会报错,因为这里仅仅是一个声明并没有初始化
    //这里我理解成Java中仅仅声明了一个对象而没有去实例化

删除操作

在map中删除,直接使用delete(map,key),删除即可

函数

我们先来看函数的语法

    func 函数名(参数列表)(返回值列表)  {
            函数逻辑
            return
    }

我们可以看到Go中返回值与Java不一样,在Java中只能有一种返回值,而在Go中却是多个返回值,这里我的意思并不是可以返回不同的值,而是可以同时返回不同的值。

func jiajian(a int, b int) (int, int) {
	return (a + b), (a - b)
}//定义了一个两个返回值的函数
add, reduce := jiajian(1, 2)//定义两个变量接收这两个返回值

说到函数,在Java中我们可以使用函数重载,在Go中这样操作是不被允许的

函数重载:指的是方法名相同,但是返回值或参数类型不同的两个或多个函数

在Go中,也是有指针的,和C/C++类似,但是Go中的指针用处非常有限,一般都使用在函数参数上,用于传给函数一个引用。

内置函数

在Go中,有很多内置函数,例如我们在学习切片的时候使用的make()函数,还有new()函数

    len()、cap()、append()、copy()、delete()、close()
    complex()、real()、imag()、panic()、recover()。。。。
    这里就不再一一赘述具体的请看Go开发手册

匿名函数

在go中支持匿名函数,但是这种函数不能单独存在,必须依托于一个变量

    a := func(x, y int) int {
            return x + y
    }
    b := a(1, 2)
    fmt.Print(b)//3
//也可以使用下面这种写法,直接在函数结尾加上括号表示赋值,需要注意的是
//这个()无论如何也不能移除即使没有参数
    c := func(x, y int) int {
            return x + y
    }(1, 2)
    fmt.Print(c)

结构体和接口

在这里我将结构体简单理解为Java中的类,我们先看一看结构体的语法结构

type 结构体名 struct{
    filed1 type
    filed2 type
    ......
}

这里我定义了一个结构体 需要注意的是,go中的结构体十分简单,它不能在结构体中写方法,只能写在结构体外,使用接收器来接收,这里我就先不赘述,后面我在详细的说。

匿名字段

因为Go语言是一种面向对象的编程语言,但是他没有封装,继承等这类思想,我们可以通过添加匿名字段来实现继承的思想

type yl struct {
	name string
	age  int	
	student
}
type student struct{
	class string
	grade string

}
//这样就可以使用继承的思想了,
//我在结构体yl中定义了一个student匿名字段,这个时候,yl结构体中继承了student的成员变量

我们称上面这种思想叫嵌入或内嵌

结构体中的字段,也可以使用结构体类型的,我们称这为聚合

接口

接口类型是Go语言的一种数据类型。和Java类似接口都是定义一组方法,而不能自我实现, 只能由其他非interface类型实现。

我们在开发Java程序的时候,在SpringBoot中我们都知道约定大于配置的法则

在Go中,我们也有一个类似的法则,就是当一个接口是一个单方法接口的时候,我们应在方法名称后加er,,当er不合适的时候,我们在前面加I或者在后面加able

我们在Go中可以实现一个接口类型的一些方法,只有我们实现了该类型的所有方法的时候,我们才称之为实现了该接口!

在接口中,可以内嵌其他接口,可以类比成Java中接口的继承,但是下面这种是不行的

type Suc interface {
    Suc1
    hello()
}
type Suc1 interface {
    Suc
    hello1()
}

也不能自己内嵌自己

type Suc interface {
    Suc
    hello1()
}

上面这两种内嵌都是错误的

下面这种才是正确的接口的内嵌

type Suc interface {	
    hello()
}
type Suc1 interface {
    Suc
    hello1()
}

接口可以内嵌多个其他接口,通过这样的方式来实现多重继承。

方法

提到方法,很多朋友可能很诧异,因为我在前面已经说过了函数,为什么又要说方法,难道它们不是一个东西吗?

 这点我在前面已经说过了,在我的理解中,方法和函数它们不是一个东西
 函数是独立与类的一种方法,它不属于任何类,而方法则是在类中才存在的
 方法可以理解成存在于类中的函数!     

在Go的方法中,存在一种与Java不同的东西,那就是接收器,我理解的接收器,作用是匹配的作用 ,多的不说,咱们代码见真章!

type yl struct {
    name string
    age  int
}

func (a yl) PrintName() {
    fmt.Print(a.name)
}

我们乍一看和之前没有任何区别,但是还是很不一样的,我们看一下之前函数的语法

    func 函数名(参数列表)(返回值列表)  {
            函数逻辑
            return
    }

这样看来就有很大不一样了吧,在这里(a yl)这就是一个接收器,这个接收器就相当于与yl这个结构体绑定,然后我们可以通过yl类的对象.方法名来调用这个方法,这样我们就可以写出方法的语法结构了。

func (参数名字 type) 方法名(参数列表)(返回值列表) {
    语法逻辑
}

注意接收器中的参数类型是在其他的或非本地的包里定义的,则会报错!!

方法也非为指针方法和值方法,这样说很笼统,简单来说,就是,在接收器这里,使用指针的就是指针方法!!!这里就不再赘述,指针方法和值方法的区别,这个和Java中,引用传递和值传递类似。

基础部分就先写到这里吧,很感谢小伙伴看到这里,不过这仅仅是Go语言基础的基础,还有很多要学习哦,加油!!!