Go编程基础(函数、方法和接口)

这篇讲的非常重要,涉及到函数、方法和接口。在实际项目中用到的非常多,注意go语言中的接口是没有继承关系的,但是可以利用接口嵌套的方式实现接口继承的功能。

1.函数function

函数function知识要点:

  • 1、Go函数不支持嵌套、重载和默认参数;
  • 2、但支持一下特性:
    • 1、无须声明原型、不定长度变参、多返回值、命令返回值参数;
    • 2、匿名函数、闭包
  • 3、定义函数使用关键字func,且左大括号不能另起一行,函数也可以作为一种类型使用

参数为不定长参数,相当于传递一个slice,如果修改参数slice中值会影响原slice的值吗?

package main
import "fmt"
func main() {
    a,b :=1,2
    B(a,b)
    fmt.Println(a,b)
}
//不定长变参的使用方法,注意这里的s相当于一个slice
//但是如果修改slice中的值会怎么呢?
func B(s ...int)  {
    s[0]=3
    s[1]=4
    fmt.Println(s)
}
image.png

注意这个传递的slice是一个值传递(slice拷贝),不会影响原slice的值。

如果传递一个slice又会怎么样呢?(内存地址的拷贝)

package main
import "fmt"
func main() {
    s1 :=[]int{1,2,3,4}
    B(s1)
    fmt.Println(s1)
}
//传递一个slice,这里的拷贝是内存地址,本质还是一个值传递
func B(s []int)  {
    s[0]=5
    s[1]=6
    s[2]=7
    s[3]=8
    fmt.Println(s)
}
image.png

指针传递(引用传递)

package main
import "fmt"
func main() {
    a:=1
    B(&a)
    fmt.Println(a)
}
//传递一个指针
func B(a *int)  {
    *a =5
    fmt.Println(*a)
}

函数本身传递

package main
import "fmt"
func main() {
    //将B函数赋值给b,然后调用b
    b:=B
    b()
}
func B()  {
    fmt.Println("Func A")
}
image.png

匿名函数传递

package main
import "fmt"
func main() {
    //匿名函数的调用
    b:=func ()  {
        fmt.Println("Func A")
    }
    b()
}

闭包(closure)

package main
import "fmt"
func main() {
    f:=closure(10)
    fmt.Println(f(1))
    fmt.Println(f(2))
}
func closure(x int) func(int) int  {
    fmt.Printf("%p\n",&x)
    return func(y int) int {
        fmt.Printf("%p\n",&x)
        return x+y
    }
}
image.png

后面一篇博客会详细讲到闭包的作用。

2.方法method

方法method的使用注意事项:

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

语法糖(Syntactic sugar),也译为糖衣语法,是由英国计算机科学家彼得·兰丁发明的一个术语,指计算机语言中添加的某种语法,这种语法对语言的功能没有影响,但是更方便程序员使用。语法糖让程序更加简洁,有更高的可读性。

举例来说,许多程序语言提供专门的语法来对数组中的元素进行引用和更新。从理论上来讲,一个数组元素的引用涉及到两个参数:数组和下标向量,比如这样的表达式,get_array(Array, vector(i, j))。然而,许多语言支持这样直接引用 Array[i, j]。同理,数组元素的更新涉及到三个参数,set_array(Array, vector(i, j), value),但是很多语言提供这样直接赋值,Array[i, j] = value。

package main
import (
"fmt"
"math"
)
type Vertex struct {
    X, Y float64
}
//注意方法的定义,这里使用的指针传递参数
func (v *Vertex) Abs() float64 {
    return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
func main() {
    //初始化结构体
    v := &Vertex{3, 4}
    //利用指针调用方法
    fmt.Println(v.Abs())
}

3.接口interface

接口interface注意事项:

  • 1、接口是一个或多个方法签名的集合;
  • 2、只要某个类型拥有该接口的所有方法签名,即算实现该接口,无需显示声明实现了哪个接口,这称为Structural Typing
  • 3、接口只有方法声明,没有实现,没有数据字段;
  • 4、接口可以匿名嵌入其他接口,或嵌入到结构中;
  • 5、将对象赋值给接口时,会发生拷贝,而接口内存存储的是指向这个复制品的指针,既无法修改复制品的状态,也无法获取指针
  • 6、只有当接口存储的类型和对象都为nil时,接口才等于nil
  • 7、接口调用不会做receiver的自动转换;接口同样支持匿名字段方法;接口也可实现类似OOP中的多态;空接口可以作为任何类型数据的容器。

接口的定义

package main
import "fmt"
//声明一个接口,里面有两个方法:Name和Connect方法
type USB interface {
    Name() string
    Connect()
}
//连接器结构体,这个类型实现了USB接口中所有方法(Name和Connect),所以PhoneConnector叫做实现了USB接口
type PhoneConnector struct {
    name string
}
func (pc PhoneConnector) Name() string  {
    return pc.name
}
func (pc PhoneConnector) Connect() {
    fmt.Println("Connect",pc.name)
}
func main() {
    //定义USB接口类型的变量
    //var a USB
    //初始化接口
    a:=PhoneConnector{"华为连接器"}
    a.Connect()
    Disconnect(a)
}
func Disconnect(usb USB) {
    fmt.Println("Disconnect")
}
image.png

嵌入接口

将上面改为嵌入接口格式为:

//声明一个接口,里面有一个Name()方法和Connecter接口
type USB interface {
    Name() string
    //将Connecter接口嵌入到USB接口中
    Connecter
}
type Connecter interface {
    Connect()
}

如何判断interface变量存储的是哪种类型(类型断言)

一个interface被多种类型实现时,有时候我们需要区分interface的变量究竟存储哪种类型的值,go可以使用comma,ok的形式做区分value,ok:=em.(T)eminterface类型的变量,T代表要断言的类型,valueinterface变量存储的值,okbool类型标识是否为该断言的类型T

//下面判断PhoneConnector是不是USB类型的
func Disconnect(usb USB) {
    if pc,ok :=usb.(PhoneConnector);ok{
        fmt.Println("Disconnect",pc.name)
        return
    }
    fmt.Println("Unknown devive")
}

空接口

interface{} 是一个空的 interface 类型,根据前文的定义:一个类型如果实现了一个 interface 的所有方法就说该类型实现了这个 interface,空的 interface 没有方法,所以可以认为所有的类型都实现了 interface{}。如果定义一个函数参数是 interface{} 类型,这个函数应该可以接受任何类型作为它的参数。

image.png

接口转换

接口只能有超接口转换子接口,相反则不行。

image.png
    //将USB接口转换为Connecter接口
    pc:=PhoneConnector{"华为连接器"}
    var a Connecter
    //转换动作
    a=Connecter(pc)
    a.Connect()

修改接口中的值,发生的是拷贝动作,不影响原来值

func main() {
    //将USB接口转换为Connecter接口
    pc:=PhoneConnector{"华为连接器"}
    var a Connecter
    a=Connecter(pc)
    a.Connect()

    //然后修改pc的name字段
    pc.name="pc"
    fmt.Println(pc.name)
    a.Connect()
}
image.png

参考资料

https://github.com/Unknwon/go-web-foundation

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,830评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,992评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,875评论 0 331
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,837评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,734评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,091评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,550评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,217评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,368评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,298评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,350评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,027评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,623评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,706评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,940评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,349评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,936评论 2 341

推荐阅读更多精彩内容