golang基础

前端之家收集整理的这篇文章主要介绍了golang基础前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

Go介绍

并发支持,垃圾回收的编译型系统编程语言。

特点:

  • 类型安全 和内存安全
  • 以非常直观和极低代价的方案实现高并发
  • 高效的垃圾回收机制
  • 快速编译 (同时解决C语言中头文件太多的问题)
  • 为多核计算机提供性能提升的方案
  • UTF-8编码支持

Go环境变量

  1. GOEXE=.exe // 形成可执行文件的后缀
  2. GOPATH // 工作目录

GOPATH下约定俗成的目录:

  1. bin // 存放编译后生成的可执行文件
  2. pkg // 存放编译后生成的包文件
  3. src // 存放项目源码

常用命令

  1. go get // 获取远程包 (git或hg(如果是谷歌code上托管))
  2. go run // 直接运行程序
  3. go build // 编译,检查是否有编译错误
  4. go fmt // 格式化源码
  5. go install // 编译包文件并且编译整个程序
  6. go test // 运行测试文件
  7. go doc // 查看文档
  8. godoc -http=:8080 // 查看文档

GO程序结构

  1. mpathapp // 可执行文件存放位置
  2. math.a // 包文件

基础知识

hello.go

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. func main () {
  6. fmt.Println("hello world")
  7. }

.go文件的一般结构

Go程序是通过package来组织的
只有package名称main的包可以包含main函数
一个可执行程序有且仅有一个main

通过import关键字来导入其它非main
通过const关键字来定义常量
通过在函数体外部使用var关键字来进行全局变量的声明和赋值
通过type关键字来进行结构struct或接口interface的声明
通过func关键字来进行函数的声明

  1. // 当前程序的包名
  2. package main
  3.  
  4. // 导入其它的包
  5. // import . "fmt" // 省略调用
  6. import (
  7. "fmt"
  8. "io"
  9. "os"
  10. "time"
  11. "strings"
  12. )
  13.  
  14. // 常量的定义
  15. const PI = 3.141592653
  16.  
  17. // 全局变量的声明与赋值
  18. var name = "zf"
  19.  
  20. // 一般类型声明
  21. type newType int
  22.  
  23. // 结构的声明
  24. type struc struct{} // 接口关键字和大括号不能有空格
  25.  
  26. // 接口的声明
  27. type inter interface{} // 接口关键字和大括号不能有空格
  28.  
  29. // 由 main 函数作为程序入口点启动
  30. func main () {
  31. fmt.Println("hello world!")
  32. }

如果导入包之后,未调用其中的函数或者类型将会报出编译错误.

package 别名

当使用第三方包时,包名可能会非常接近或者相同,此时就可以使用别名来进行区别和调用

  1. import std "fmt" // 别名
  2.  
  3. std.Println("hello world")

注释

  1. // 单行注释
  2. /* 多行注释 */

可见性规则

Go语言中,使用大小写来决定该常量,变量,类型,接口,结构,或函数是否可以被外部包所调用:根据约定,函数名首字母小写即为private;函数名首字母大写即为public

类型与变量

基本类型

布尔型:bool

长度:1字节
取值范围:true,false
注意:不可以用数字代表true或false

整型:int/uint

根据运行平台可能为32或64位

  • 8位整型:int8/uint8

    1. 长度:1字节
    2. 取值范围:-128~127/0~255
  • 16位整型:int16/uint16

    1. 长度:2字节
    2. 取值范围:-32768~32767/0~65535
  • 32位整型:int32(rune)/uint32

    1. 长度:4字节
    2. 取值范围:-2^32/2~2^32/2-1/0~2^32-1
  • 64位整型:int64/uint64

    1. 长度:8字节
    2. 取值范围:-2^64/2~2^64/2-1/0~2^64-1
  • 字节型:byte(uint8别名)

从严格意义上讲type newint int 这里的newinting不能说是int的别名,而是底层数据结构相同,在这里自定义类型,在进行类型转换时扔旧需要显示转换,但byterune确实为uint8int32的别名,可以相互进行转换。

浮点型:float32/float64

长度:4/8字节
小数位:精确到7/15小数位

复数:complex64/complex128

长度:8/16字节

足够保存指针的 32 位或 64 位整数型:uintptr

其它值类型

array、struct、string

引用类型

slice、map、chan

接口类型

interface

函数类型

func

类型零值

零值并不等于空值,而是当变量被声明为某种类型后的默认值。

通常情况下:

  • 值类型的默认值是为0
  • bool为false
  • string为空字符串

变量

单个变量的声明与赋值

变量的声明格式:var <变量名称> <变量类型>
变量的赋值格式: <变量名称> = <表达式>
声明的同时赋值:var <变量名称> [变量类型] = <表达式>
写法:

  1. var a int // 变量声明
  2. a = 10 // 变量赋值
  3.  
  4. var b int = 20 // 变量声明的同时赋值
  5. var b = 1 // 变量声明与赋值,由系统推荐是那种类型
  6.  
  7. b := 10 // 函数中的变量声明与赋值的最简写法
  8.  
  9. var 是全局的变量
  10. := 只能在函数中使用,局部变量

多个变量的声明与赋值

全局变量的声明可使用var()的方式进行简写
全局的变量的声明不可以省略var,但可使用并行方式
所有变量都可以使用类型推断
局部变量不可以使用var()的方式简写,只能使用并行方式

  1. var (
  2. // 使用常规方式
  3. aaa = "hello"
  4. // 使用并行方式以及类型推断
  5. a,b = 1,2
  6. // cc := 2 // 不可以省略 var
  7. )
  8.  
  9.  
  10. func main () {
  11. // 多个变量的声明
  12. var a,b,c,d int
  13. // 多个变量的赋值
  14. a,d = 1,2,3,4
  15.  
  16. // 多个变量声明的同时赋值
  17. var e,f,g,h int = 5,6,7,8
  18. // 省略变量类型,由系统推断
  19. var i,j,k,l = 9,10,11,12
  20. // 多个变量声明与赋值的最简写法
  21. i,m,n,o := 13,14,15,16
  22.  
  23. _,dd = 10,20 // 空白符号,省略该表达式赋值(应用函数返回值)
  24. }

类型转换

  • Go中不存在隐式转换,都是显示声明(Go的类型安全)
  • 转换只能发生在两种相互兼容的类型之间
  • 类型转换的格式:

    1. <ValueA> [:]= <TypeOfValueA>(<ValueB>)
  1. // 在相互兼容的两种类型之间转换
  2. var a float32 = 1.1
  3. b := int(a)
  4.  
  5.  
  6. // 表达式无法通过编译
  7. var c bool = true
  8. d := int(c)

  1. package main
  2.  
  3. import (
  4. "fmt"
  5. )
  6.  
  7. func main () {
  8. var a float32 = 100.01
  9. fmt.Println(a) // 100.01
  10. b := int(a)
  11. fmt.Println(b) // 100
  12. }

整型无法和布尔型兼容
float类型无法和字符串类型兼容

intstring互转

  1. var c int = 3
  2. // d := string(c)
  3. d := strconv.Itoa(c) // 字符串 3
  4. c,_ = strconv.Atoi(d) // int 3

现象:

  1. var a int = 65
  2. string(a)
  3. fmt.Println(a) // A

string()表示将数据转换成文本格式,因为计算机中存储的任何东西本质上都是数字,因此此函数自然的认为需要的是用数字65表示文本A

常量

  • 常量的值在编译时就已经确定
  • 常量的定义格式与变量基本相同
  • 等号右侧必须是常量或者常量表达式
  • 常量表达式中的函数必须是内置函数

常量的初始化规则与枚举

  • 在定义常量组时,如果不提供初始值,则表示将使用上行的表达式
  • 使用相同的表达式不代表具有相同的值
  • iota是常量的计数器,从0开始,组中每定义1个常量自动递增1
  • 通过初始化规则与iota可以达到枚举的效果
  • 每遇到一个const关键字,iota就会重置为0
  1. const (
  2. _A = "A"
  3. _B
  4. _C = iota
  5. _D
  6. )
  7. func main () {
  8. fmt.Println(_A,_B,_C,_D) // A A 2 3
  9. }

  1. const (
  2. a = "123"
  3. b = len(a)
  4. c
  5. )
  6.  
  7. func main () {
  8. fmt.Println(a,c) // 123,3
  9. }

编译不通过:

  1. var ss = "123"
  2.  
  3. const (
  4. a = len(ss)
  5. b
  6. c
  7. )
  8.  
  9. func main () {
  10. fmt.Println(a,c)
  11. }

错误信息:

  1. # command-line-arguments
  2. .\const.go:39: const initializer len(ss) is not a constant

  1. const (
  2. a,"xixi"
  3. c
  4. )
  5.  
  6. func main () {
  7. fmt.Println(a,c)
  8. }

错误信息:

  1. # command-line-arguments
  2. .\const.go:40: extra expression in const declaration

运算符

Go中的运算符从左至右结合

优先级(从高到低)

  • ^ ! (一元运算符)
  • * / % << >> & &^ (二元运算符)
  • + - | ^ (二元运算符)
  • == != < <= >= > (二元运算符)
  • <- (专门用于channel)
  • &&
  • ||
  1. fmt.Println(1 ^ 2) // 二元运算符
  2. fmt.Println(^2) // 一元运算符
  3.  
  4. /*
  5.  
  6. 6: 0110
  7. 11: 1101
  8. ------------
  9. & 0010 // 2
  10. | 1111 // 15
  11. ^ 1101 // 13
  12. &^ 0100 // 4
  13.  
  14. 6 -> 110
  15. 5 -> 101
  16. 4 -> 100
  17.  
  18. 13 / 2 = 1 // 6
  19. 1101
  20. */

控制语句

指针

Go虽然保留了指针,但与其他编程语言不同的是,在Go当中不支持指针运算以及->运算符,而是直接采用.选择符来操作指针目标对象的成员

  • 操作符&取变量地址,使用*通过指针间接访问目标对象
  • 默认值为nil而非NULL
  1. package main
  2.  
  3. import (
  4. "fmt"
  5. )
  6.  
  7. func main () {
  8. a := 1
  9. var p *int = &a
  10. fmt.Println(p) // 0xc0420361d0
  11. fmt.Println(*p) // 1
  12. }

递增递减语句
在Go当中,++--是作为语句而并不是作为表达式

判断if

  • 条件表达式没有括号
  • 支持一个初始化表达式(可以是并行方式)
  • 左大括号必须和条件语句或else在同一行
  • 支持单行模式
  • 初始化语句中的变量为block级别,同时隐藏外部同名变量
  1. func main () {
  2. a := 10
  3. if a := 0; a > 0 {
  4. fmt.Println(a)
  5. } else if a == 0 {
  6. fmt.Println(0111) // 73
  7. }
  8. fmt.Println(a) // 10
  9. }

循环for

  • Go只有for一个循环语句关键字,但支持3中形式
  • 初始化和step表达式可以是多个值
  • 条件语句每次循环都会重新检查,因此不建议在条件语句中使用函数,尽量提前计算好条件并以变量或常量代替
  • 左大括号必须和条件语句在同一行
  1. // 第一种形式
  2. func main () {
  3. a := 1
  4. for {
  5. a++
  6. if a > 3 {
  7. break
  8. }
  9. fmt.Println(a) // 2,3
  10. }
  11. fmt.Println(a) // 4
  12. }

  1. // 第二种形式
  2. func main () {
  3. a := 1
  4. for a <= 3 {
  5. a++
  6. fmt.Println(a) // 2,4
  7. }
  8. fmt.Println(a) // 4
  9. }

  1. // 第三种形式
  2. func main () {
  3. a := 1
  4. for i := 0; i < 3; i++ {
  5. a++
  6. fmt.Println(a) // 2,4
  7. }
  8. fmt.Println(a) // 4
  9. }

swtich

  • 可以使用任何类型或表达式作为条件语句
  • 不需要break,一旦条件符合自动终止
  • 如希望继续执行下一个case,需使用fallthrough语句
  • 支持下一个初始化表达式(可以是并行方式),右侧需跟分号
  • 做大括号必须和条件语句在同一行
  1. func main () {
  2. a := 1
  3. switch a {
  4. case 0:
  5. fmt.Println("a=0")
  6. case 1:
  7. fmt.Println("a=1")
  8. }
  9. fmt.Println(a)
  10. }

  1. func main () {
  2. a := 1
  3. switch {
  4. case a >= 0:
  5. fmt.Println("a>=0")
  6. fallthrough
  7. case a >= 1:
  8. fmt.Println("a>=1")
  9. }
  10. fmt.Println(a)
  11. }

  1. func main () {
  2. switch a := 1; {
  3. case a >= 0:
  4. fmt.Println("a>=0")
  5. fallthrough
  6. case a >= 1:
  7. fmt.Println("a>=1")
  8. default:
  9. fmt.Println("none")
  10. }
  11. fmt.Println(a) // undefined: a //for,if,switch都具有块级作用域
  12. }

跳转语句goto,break,continue

  • 三个语法都可以配合标签使用
  • 标签名区分大小写,若不使用会造成编译错误
  • breakcontinue配合标签可用于多层循环的跳出
  • goto调整执行位置,与其它2个语句配合标签的结果并不相同
  1. func main () {
  2. LABEL:
  3. for {
  4. for i := 0; i < 10; i++ {
  5. if i > 2 {
  6. break LABEL
  7. } else {
  8. fmt.Println(i)
  9. }
  10. }
  11. }
  12. }

  1. func main () {
  2. LABEL:
  3. for i := 0; i < 10; i++ {
  4. for {
  5. fmt.Println(i)
  6. continue LABEL
  7. }
  8. }
  9. }

数组Array

  • 定义数组的格式:var <varName> [n]<type>,n>=0
  • 数组的长度也是类型的一部分,因此具有不同长度的数组为不同类型
  • 数组在Go中为值类型
  • 数组之间可以使用==!=进行比较,但不可以使用<或>``(相同类型之间,才可以使用相等或不能判断。也就是数组长度也要相同,长度也是数组类型的一部分)
  • 可以使用new来创建数组,此方法返回一个指向数组的指针
  • Go支持多维数组

创建数组

  1. func main () {
  2. var a [2]string
  3. var b [1]int
  4. c := [2]int{11,12}
  5. d := [20]int{19: 1}
  6. e := [...]int{1,4,5}
  7. f := [...]int{0: 11,1: 22,2: 33}
  8. b[0] = 10
  9. a[1] = "100"
  10. arr := [...]string{0: "xixi",1: "hhh"}
  11. fmt.Println(a,d,e,f)
  12. }

  1. p := new([10]int)
  2. p[1] = 2
  3. fmt.Println(&p) // 取地址
  4. fmt.Println(*p) // 取值

  1. // 多维数组
  2. a := [2][3]int{
  3. {1,1,1},{2,2},}
  4. fmt.Println(a)

冒泡排序:

  1. func main () {
  2. a := [...]int{3,234,5}
  3. fmt.Println(a)
  4. num := len(a)
  5. for i := 0; i< num; i++ {
  6. for j := i+1; j < num; j++ {
  7. if a[i] < a[j] {
  8. temp := a[i]
  9. a[i] = a[j]
  10. a[j] = temp
  11. }
  12. }
  13. }
  14. fmt.Println(a)
  15. }

切片Slice

  • 其本身并不是数组,它指向底层的数组
  • 作为变长数组的代替方案,可以关联底层数组的局部或全部
  • 为引用类型
  • 可以直接创建或从底层数组获取生成
  • 使用len()获取元素个数,cap()获取容量
  • 一般使用make()创建
  • 如果多个slice指向相同底层数组,其中一个的值改变会影响全部
  • make([]T,len,cap)

    1. 其中`cap`可以省略,则和`len`的值相同
    2. `len`表示存数的元素个数,`cap`表示容量

声明:

  1. // 声明方法
  2. var s1 []int // 中括号中没有数字或`...`
  3. fmt.Println(s1) // []

reslice方法: 从数组中截取Slice

  1. a := [...]int{1,5,8,9}
  2. fmt.Println(a)
  3. s1 := a[5: len(a)] // 包含起始索引,不包含终止索引 // a[5 6 7 8 9]
  4. s2 := a[5: ] // 包含起始索引,不包含终止索引 // a[5 6 7 8 9]
  5. fmt.Println(s1,s2)

make方法 (一般使用make创建)

  1. s1 := make([]int,10) // 10小块连续的内存,如果slice超过10,内存卡会继续申请,重新生成内存地址
  2. s2 := make([]int,10) // cap不给定,是slice的最大长度
  3. fmt.Println(len(s1),cap(s1),s1) // 3 10 [0 0 0]
  4. fmt.Println(len(s2),cap(s2),s2) // 10 10 [0 0 0 0 0 0 0 0 0 0]

Reslice

  • reslice时索引以被slice的切片为准
  • 索引不可以超过被slice的切片的容量cap()
  • 索引越界不会导致底层数组的重新分配而引发错误

Append

  • 可以在slice尾部追加元素
  • 可以将一个slice追加在另一个slice尾部
  • 如果最终长度为超过追加到slice的容量则返回元素slice
  • 如果超过追加到的slice的容量则将重新分配数组并拷贝原始数据
  1. s1 := make([]int,6)
  2. fmt.Println("%p\n",s1)
  3. s1 = append(s1,4)
  4.  
  5. fmt.Println("%v %p\n",s1) // [0 0 0 1 2 3 4]

Copy

  1. nt{1,7}
  2. s2 := []int{8,9}
  3. copy(s1,s2)
  4. // copy(s1,s2[1: 2])
  5. fmt.Println(s1,s2) // [8 9 3 4 5 6 7] [8 9]

Map

  • 类似其它语言中的哈希表或者字典,以key-value形式存储的数据
  • key必须是支持==!=比较运算符的类型,不可以是函数mapslice
  • Map查找比线性搜索快很多,但比使用索引访问数据的类型慢100倍
  • Map使用make()创建,支持:=简写方式
  • 键值对不存在时自动添加,使用delete()删除某键值对
  • 使用for rangemapslice进行迭代操作
  • make([keyType]valueType,cap),cap表示容量,可省略

    1. 超过容量时会自动扩容,但尽量提供一个合理的初始值
    2. 使用`len()`获取元素个数

Map初始化

  1. var m map[int]string
  2. // m = map[int]string{}
  3. m = make(map[int]string)
  4. var m1 map[int]string = make(map[int]string)
  5. m2 := make(map[int]string)
  6.  
  7. fmt.Println(m,m1) // map[]

删除和常用Map方法赋值

  1. m2 := make(map[int]string)
  2. m2[1] = "OK"
  3. delete(m2,1)
  4. a := m2[1]
  5.  
  6. fmt.Println(a)

迭代:

  1. for i,v := range slice {
  2. // slice[i]
  3. }
  4.  
  5. for k,v := range map {
  6. // map[k]
  7. }

取Map中的key

  1. m := map[int]string{1: "A",2: "B",3: "C",4: "D"}
  2. s := make([]int,len(m))
  3. i := 0
  4. for k,_ := range m {
  5. s[i] = k
  6. i++
  7. }
  8. sort.Ints(s)
  9. fmt.Println(s)

Map中的 key-value互换:

  1. m1 := map[int]string{1: "A",3: "C"}
  2. m2 := make(map[string]int)
  3. // m2 := map[string]int{"A": 1,"B": 2,"C": 3}
  4.  
  5. for k,v := range m1 {
  6. m2[v] = k
  7. }
  8. fmt.Println(m1)
  9. fmt.Println(m2)

Function

函数function

Go 函数 不支持嵌套重载默认参数
支持的特性:

  • 无需声明原型
  • 不定长度变参
  • 多返回值
  • 命名返回值参数
  • 匿名函数
  • 闭包

定义函数使用关键字 func,且左大括号不能另起一行
函数也可以作为一种类型使用

闭包:

  1. func closure (x int) func (int) int {
  2. return func (y int) int {
  3. return x + y
  4. }
  5. }

defer

  • defer的执行方式类似其它语言中的析构函数,在函数体执行结束后按照调用顺序的相反顺序逐个执行
  • 即使函数发生严重错误也会执行
  • 支持匿名函数调用
  • 常用于资源清理文件关闭解锁以及记录时间等操作
  • 通过与匿名函数配合可在return之后修改函数计算结果
  • 如果函数体内某个变量作为defer时匿名函数的参数,则在定义defer时即已经获得了拷贝,否则则是引用某个变量的地址
  • Go 没有异常机制,但有panic/recover模式来处理错误
  • panic可以在任何地方引发,但recover只有在defer调用函数中有效

defer使用:

  1. func main () {
  2. fmt.Println("a")
  3. defer fmt.Println("b")
  4. defer fmt.Println("c")
  5. // a,b
  6. for i := 0; i < 3; i++ {
  7. defer fmt.Println(i) // 2 1 0
  8. }
  9. for i := 0; i < 3; i++ {
  10. defer func () {
  11. fmt.Println(i) // 3 3 3
  12. }()
  13. }
  14.  
  15. }

defer要放在panic()之前:

  1. func main () {
  2. A()
  3. B()
  4. C()
  5. }
  6.  
  7. func A () {
  8. fmt.Println("func A")
  9. }
  10.  
  11. func B () {
  12. defer func () {
  13. if err := recover(); err != nil {
  14. fmt.Println("Recover")
  15. }
  16. }()
  17. panic("Panic in B")
  18. }
  19.  
  20. func C () {
  21. fmt.Println("func C")
  22. }

结构struct

  • Go 中的struct与C中的struct非常相似,并且Go没有class
  • 使用 type <Name> struct{} 定义结构,名称遵循可见性规则
  • 支持指向自身的指针类型成员
  • 支持匿名结构,可用作成员或定义成员变量
  • 匿名结构也可以用于map的值
  • 可以使用字面值对结构进行初始化
  • 允许直接通过指针来读写结构成员
  • 相同类型的成员可进行直接拷贝赋值
  • 支持 ==!=比较运算符,但不支持 ><
  • 支持匿名字段,本质上是定义了以某个类型名为名称的字段
  • 嵌入结构作为匿名字段看起来像继承,但不是继承
  • 可以使用匿名字段指针
  1. type person struct {
  2. name string
  3. age int
  4. }
  5.  
  6. func main () {
  7. a := person{}
  8. a.name = "zf"
  9. a.age = 23
  10. fmt.Println(a) // { 0}
  11. }

struct也是值类型

对初始化结构struct使用地址符

  1. type person struct {
  2. name string
  3. age int
  4. }
  5. func main () {
  6. a := &person{ // 调用结构使用地址符 // 字面值初始化
  7. name: "zf",age: 24,}
  8. a.name = "pink"
  9. // a.name = "zf"
  10. // a.age = 23
  11. fmt.Println(a) // { 0}
  12. // A(&a)
  13. A(a)
  14. B(a)
  15. fmt.Println(a)
  16. }
  17.  
  18. func A (per *person) {
  19. per.age = 18
  20. fmt.Println("A",per)
  21. }
  22.  
  23. func B (per *person) {
  24. per.age = 20
  25. fmt.Println("B",per)
  26. }

匿名结构:

  1. func main () {
  2. a := &struct {
  3. name string
  4. age int
  5. } {
  6. name: "tan",age: 19,}
  7. fmt.Println(a)
  8. }

外层结构:

  1. type person struct {
  2. name string
  3. age int
  4. contact struct {
  5. phone,city string
  6. }
  7. }
  8.  
  9. func main () {
  10. b := person {
  11. name: "yellow",age: 18,}
  12. b.contact.phone = "123123"
  13. b.contact.city = "xiamen"
  14.  
  15. fmt.Println(b)
  16. }

匿名字段:

  1. type p1 struct {
  2. string
  3. int
  4. }
  5.  
  6. func main () {
  7. c := p1{"cyan",20} // 字段的类型严格按照结构声明的字段
  8.  
  9. fmt.Println(a,c)
  10. }

匿名函数和匿名字段在函数中使用的次数非常少,没有必要声明,才会使用到。

嵌入(继承)结构:

  1. type human struct {
  2. Sex int
  3. }
  4.  
  5. type teacher struct {
  6. human
  7. name string
  8. age int
  9. }
  10.  
  11. type student struct {
  12. human
  13. name string
  14. age int
  15. }
  16.  
  17. func main () {
  18. // a := teacher{name: "cyan",age: 20,human{sex: 0}}
  19. a := teacher{name: "cyan",human: human{Sex: 0}}
  20. b := student{name: "pink",age: 22,human: human{Sex: 1}}
  21.  
  22. a.name = "xixi"
  23. a.age = 23
  24. // a.Sex = 100
  25. a.human.Sex = 200
  26.  
  27. fmt.Println(a,b)
  28. }

方法method

  • Go 中虽没有class,但依旧有method
  • 通过显示说明receiver来实现与某个类型的组合
  • 只能为同一个包中的类型定义方法
  • Receiver 可以是类型的值或者指针
  • 不存在方法重载
  • 可以使用值或指针来调用方法,编译器会自动完成转换
  • 从某种意义上来说,方法函数的语法糖,因为receiver其实就是
  • 方法所接收的第1个参数(Method Value vs. Method Expression)
  • 如果外部结构和嵌入结构存在同名方法,则优先调用外部结构的方法
  • 类型别名不会拥有底层类型所附带的方法
  • 方法可以调用结构中的非公开字段

  1. type Test struct {
  2. name string
  3. }
  4.  
  5. type Person struct {
  6. name string
  7. }
  8.  
  9. func main () {
  10. t := Test{}
  11. t.Print()
  12. fmt.Println(t.name)
  13.  
  14. p := Person{}
  15. p.Print()
  16. fmt.Println(p.name)
  17. }
  18.  
  19. func (t *Test) Print() {
  20. t.name = "red"
  21. fmt.Println("Test")
  22. }
  23.  
  24. func (p Person) Print() {
  25. fmt.Println("Person")
  26. }

  1. // 类型别名不会拥有底层类型所附带的方法
  2. type TZ int
  3.  
  4. func main () {
  5. var a TZ
  6. a.Print()
  7. (*TZ).Print(&a)
  8. }
  9.  
  10. func (a *TZ) Print() {
  11. fmt.Println("TZ")
  12. }

方法不同调用方式

  1. type A struct {
  2. name string
  3. }
  4.  
  5. func main () {
  6. a := A{}
  7. a.Print()
  8. // (*TZ).Print(&a)
  9. }
  10.  
  11. func (a *A) Print() {
  12. a.name = "123"
  13. fmt.Println(a.name)
  14. // fmt.Println("TZ")
  15. }

方法访问权限
struct中的私有属性,在方法中可以访问

  1. // 属性的访问范围是在`package`中的可以访问的,如果需要在外部包中访问,需要大写字母
  2. type A struct {
  3. name string
  4. }
  5.  
  6. func main () {
  7. a := A{}
  8. a.Print()
  9. fmt.Println(a.name)
  10. }
  11.  
  12. func (a *A) Print() {
  13. a.name = "123"
  14. fmt.Println(a.name)
  15. }

猜你在找的Go相关文章