Go学习笔记

妖狐艹你老母 2022-11-03 15:29 229阅读 0赞

Go

文章目录

  • Go
    • 变量
    • 指针
    • Go函数
    • Go面向对象
      • 继承
      • 接口
    • 数据结构
      • 链表

变量

变量声明

  1. //1、单变量声明,类型放在变量名之后,可以为任意类型
  2. var 变量名 类型
  3. var v1,v2,v3 string //多变量同类型声明
  4. //2、多变量声明
  5. var {
  6. v1 int
  7. v2 []int
  8. }

变量初始化

  1. //1、使用关键字var,声明变量类型并赋值
  2. var v1 int=10
  3. //2、使用关键字var,直接对变量赋值,go可以自动推导出变量类型
  4. var v2=10
  5. //3、直接使用“:=”对变量赋值,不使用var,两者同时使用会语法冲突,推荐使用
  6. v3:=10

匿名变量

  1. //Go中所有声明后的变量都需要调用到,当出现函数多返回值,并且部分返回值不需要使用时,可以使用匿名变量丢弃该返回值
  2. func GetName()(firstName,lastName,nickName string){
  3. return "May","Chan","Make"
  4. }
  5. _,_,nickName:=GetName() //使用匿名变量丢弃部分返回值

指针

指针(pointer)在Go语言中可以被拆分为两个核心概念:

  • 类型指针,允许对这个指针类型的数据进行修改,传递数据可以直接使用指针,而无须拷贝数据,类型指针不能进行偏移和运算。(类似Java中的引用)
  • 切片,由指向起始元素的原始指针、元素数量和容量组成。

每个变量在运行时都拥有一个地址,这个地址代表变量在内存中的位置。Go语言中使用在变量名前面添加&操作符(前缀)来获取变量的内存地址(取地址操作)

取地址操作符&和取值操作符*是一对互补操作符,&取出地址,*根据地址取出地址指向的值。

  1. func main() {
  2. str := "test ptr"
  3. fmt.Println(&str) // &T 取变量T的内存地址值赋值到ptr 0xc000010200 返回的是指针类型
  4. fmt.Println(*&str) // *ptr 取指定内存地址对应的变量值 test ptr 返回的是值类型
  5. }

变量、指针地址、指针变量、取地址、取值的相互关系和特性如下:

  • 对变量进行取地址操作使用&操作符,可以获得这个变量的指针变量。
  • 指针变量的值是指针地址。
  • 对指针变量进行取值操作使用*操作符,可以获得指针变量指向的原变量的值。

通过指针修改数据

  1. // 交换函数
  2. func swap1(a, b *int) {
  3. // 取a指针的值, 赋给临时变量t
  4. t := *a
  5. // 取b指针的值, 赋给a指针指向的变量
  6. *a = *b
  7. // 将a指针的值赋给b指针指向的变量
  8. *b = t
  9. }
  10. func main() {
  11. // 准备两个变量, 赋值1和2
  12. x, y := 1, 2
  13. // 交换变量值
  14. swap1(&x, &y)
  15. // 输出变量值
  16. fmt.Println(x, y)
  17. }

new() 函数可以创建一个对应类型的指针,创建过程会分配内存,被创建的指针指向默认值。

  1. func new(Type) *Type
  2. // new() 创建指针的另一种手段
  3. str := new(string)
  4. *str = "test new"
  5. fmt.Println(str) // 0xc000010200
  6. fmt.Println(*str)

go和java类似,都是值传递,修改的是传入值的副本

  1. type Person struct {
  2. name string
  3. age int
  4. }
  5. func updateAge(p Person){
  6. p.age = 10
  7. }
  8. func updateAgeByPtr(p *Person) {
  9. p.age = 10
  10. }
  11. func main() {
  12. p := Person{
  13. age: 0,name: "kevin"}
  14. fmt.Println(p.age)
  15. updateAge(p) // go中是值传递
  16. fmt.Println(p.age)
  17. updateAgeByPtr(&p)
  18. fmt.Println(p.age)
  19. }

变量声明而没有赋值,默认为零值,不同类型零值不同,例如字符串零值为空字符串;

指针声明而没有赋值,默认为nil,即该指针没有任何指向。当指针没有指向的时候,不能对(*point)进行操作包括读取,否则会报空指针异常。

  1. var aPot *string
  2. fmt.Println(aPot) // <nil>

指针也是一种类型,不同于一般类型,指针的值是地址,这个地址指向其他的内存,通过指针可以读取其所指向的地址所存储的值。
函数方法的接受者,也可以是指针变量。无论普通接受者还是指针接受者都会被拷贝传入方法中,不同在于拷贝的指针,其指向的地方都一样,只是其自身的地址不一样。

Go函数

Go函数中只关注匿名函数和闭包

所谓闭包就是函数的返回值是也是一个函数

  1. // case1
  2. func foo1(x *int) func() {
  3. // 返回值是一个函数
  4. return func() {
  5. *x = *x + 1
  6. fmt.Printf("foo1 val = %d\n", *x)
  7. }
  8. }
  9. // case2
  10. func foo2(x int) func() {
  11. return func() {
  12. x = x + 1
  13. fmt.Printf("foo1 val = %d\n", x)
  14. }
  15. }
  16. func main() {
  17. x := 133
  18. f1 := foo1(&x)
  19. f1()
  20. fmt.Println(x)
  21. y := 100
  22. f2 := foo2(y)
  23. f2()
  24. fmt.Println(y)
  25. }

执行结果:

  1. foo1 val = 134
  2. 134
  3. foo1 val = 101
  4. 100

case1和case2的区别在于值传递和引用传递的区别,go和Java一样只有值传递,这里所说的引用传递是传递的是地址的值

闭包的延迟绑定

只有在执行闭包函数的时候才会去寻找最新的函数环境

  1. // case7 闭包的延迟绑定,
  2. func foo7(x int) []func() {
  3. var fs []func()
  4. values := []int{
  5. 1, 2, 3, 4, 5}
  6. for _, val := range values {
  7. fs = append(fs, func() {
  8. fmt.Printf("foo7 val = %d\n", x+val)
  9. })
  10. }
  11. return fs
  12. }
  13. func main() {
  14. fs := foo7(11)
  15. for _, f := range fs{
  16. f()
  17. }
  18. }

答案是:(在用到的时候去寻找函数的最新环境,此时是val 是 5)

  1. foo7 val = 16
  2. foo7 val = 16
  3. foo7 val = 16
  4. foo7 val = 16

Go面向对象

继承

在Go语言中,并没有显式的继承与显式的接口实现(接口实现其实也算是一种继承),Go对于继承,是通过组合来实现的

  1. // 继承
  2. type People struct {
  3. name string
  4. age int
  5. }
  6. type Teacher struct {
  7. People // 以组合的方式引入
  8. teacherSomeThing string
  9. }

接口

go中的接口不能有变量,go中实现接口是基于方法,如果一个类实现了这个接口中所有的方法,那么这个类就实现了这个接口

  1. import "fmt"
  2. // 只有实现了接口中的所有方法才是实现了这个接口
  3. type Usb interface {
  4. start()
  5. stop()
  6. }
  7. type Usb1 interface {
  8. start()
  9. stop()
  10. }
  11. // computer既实现了Usb1也实现了Usb接口
  12. type computer struct {
  13. }
  14. // 实现start
  15. func (c computer)start() {
  16. fmt.Println("调用start")
  17. }
  18. // 实现stop
  19. func (c computer) stop() {
  20. fmt.Println("调用stop")
  21. }
  22. func testUsb(u Usb) {
  23. u.start()
  24. u.stop()
  25. }
  26. func main() {
  27. c := computer{
  28. }
  29. testUsb(c)
  30. }

从接口看go中的错误处理

  1. // 内置的error接口,是一个常规的用于处理错误的接口。
  2. // 其中 nil 表示没有错误。
  3. type error interface {
  4. Error() string
  5. }

实现自定义异常只需要实现这个error接口

  1. type MyError struct {
  2. errorMsg string
  3. }
  4. func (error MyError) Error() string{
  5. return error.errorMsg
  6. }
  7. func main() {
  8. myError := MyError{
  9. errorMsg : "catch error",
  10. }
  11. fmt.Println(myError.Error())
  12. }

数据结构

链表

发表评论

表情:
评论列表 (有 0 条评论,229人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Go语言学习笔记(一)

    Go语言学习笔记(一) 本博客是为了记录在学习Go语言过程中应该需要特别记忆的知识点,以防后续需要查看时可以到博客中查找之前的学习记录。本系列博客内容都来自于人民邮电出版

    相关 Go学习笔记

    \\\看了两周七牛团队翻译的《Go语言程序设计》,基本上领略到了Go语言的魅力。学习一个语言,语法什么的任何人都是很容易学会,难就难在充分领略到这门编程语言的思想。\\\ \\