我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Go语言函数、结构体、方法和接口怎么用

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Go语言函数、结构体、方法和接口怎么用

本篇内容介绍了“Go语言函数、结构体、方法和接口怎么用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

    1. 函数

    Go语言的函数属于“一等公民”(first-class),也就是说:

    • 函数本身可以作为值进行传递。

    • 支持匿名函数和闭包(closure)。

    • 函数可以满足接口。

    1.1 函数返回值

    同一种类型返回值
    func typedTwoValues() (int, int) {    return 1, 2}a, b := typedTwoValues()fmt.Println(a, b)
    带变量名的返回值
    func named Ret Values() (a, b int) {       a = 1       b = 2       return}

    函数使用命名返回值时,可以在return中不填写返回值列表,如果填写也是可行的

    函数中的参数传递

    Go语言中传入和返回参数在调用和返回时都使用 值传递 ,这里需要注意的是 指针、切片和map等引用型对象指向的内容在参数传递中不会发生复制,而是将指针进行复制,类似于创建一次引用。

    函数变量

    在Go语言中,函数也是一种类型,可以和其他类型一样被保存在变量中

    func fire() {fmt.Println("fire")}func main() {var f func()  //将变量f声明为func()类型,此时f就被俗称为“回调函数”。此时f的值为nil。f = firef()}

    1.2 匿名函数——没有函数名字的函数

    Go语言支持匿名函数,即在需要使用函数时,再定义函数,匿名函数没有函数名, 只有函数体 ,函数可以被作为一种类型被赋值给函数类型的变量, 匿名函数也往往以变量方式被传递 。

    在定义时调用匿名函数

    匿名函数可以在声明后调用,例如:

    func(data int) {     fmt.Println("hello", data)}(100)
    将匿名函数赋值给变量

    匿名函数体可以被赋值,例如:

    // 将匿名函数体保存到f()中f := func(data int) {       fmt.Println("hello", data)}// 使用f()调用f(100)
    匿名函数用作回调函数

    使用时再定义匿名函数,不使用先在被调用函数里面进行声明,这就是回调精髓

    // 遍历切片的每个元素,通过给定函数进行元素访问   func visit(list []int, f func(int)) {        for _, v := range list {              f(v)        }   }   func main() {       // 使用匿名函数打印切片内容        visit([]int{1, 2, 3, 4}, func(v int) {              fmt.Println(v)        })   }
    可变参数——参数数量不固定的函数形式

    所有参数都是可变参数:fmt.Println

    func Println(a ...interface{}) (n int, err error) {    return Fprintln(os.Stdout, a...)}

    fmt.Println在使用时,传入的值类型不受限制,例如:

    fmt.Println(5, "hello", &struct{ a int }{1}, true)

    当可变参数为 interface{} 类型时,可以传入任何类型的值

    部分参数 是可变参数:fmt.Printf

    fmt.Printf的第一个参数为参数列表,后面的参数是可变参数:

    func Printf(format string, a ...interface{}) (n int, err error) {return Fprintf(os.Stdout, format, a...)}------------------------------------------------------fmt.Printf("pure string\n")fmt.Printf("value: %v %f\n", true, math.Pi)

    1.3 闭包

    闭包可以理解成定义在函数内部的一个函数。本质上,闭包是函数内部和函数外部连接起来的桥梁。简单来说,闭包=函数+引用环境

    func main() {var f = add()fmt.Printf("f(10): %v\n", f(10))fmt.Printf("f(20): %v\n", f(20))// f(10): 10// f(20): 30}func add() func(int) int {var x intreturn func(y int) int {x += yreturn x}}

    1.4 defer语句

    defer语句将其后面跟随的语句进行延迟处理,被defer的语句按先进后出的方式执行(最先defer的语句最后执行,后被defer的语句先执行)。

    特性:

    • 关键字defer用于注册延迟调用

    • 直到调用return之前才执行(故可用来作资源清理)

    • 多个defer语句,FILO方式执行

    • defer中的变量,在defer声明时就定义了

    用途:

    • 关闭文件句柄

    • 锁资源释放

    • 数据库连接释放

    处理运行时发生的错误

    Go语言的错误处理思想及设计包含以下特征:

    •  一个可能造成错误的函数,需要返回值中返回一个 错误接口(error )。如果调用是成功的,错误接口将返回nil,否则返回错误。

    • 在函数调用后需要检查错误,如果发生错误,进行必要的错误处理。

    错误接口的定义格式

    error是Go系统声明的接口类型,代码如下:

    type error interface {    Error() string    // 返回错误的具体描述.}

    所有符合Error() string格式的接口都能实现错误接口。

    定义一个错误

    在Go语言中,使用errors包进行错误的定义,格式如下:

    var err = errors.New("this is an error")

    错误字符串由于相对固定,一般在包作用域声明, 应尽量减少在使用时直接使用errors.New返回。

    宕机(panic)——程序终止运行

    手动触发宕机

    Go语言可以在程序中手动触发宕机,让程序崩溃,这样开发者可以及时地发现错误,同时减少可能的损失。

    Go语言程序在宕机时,会将堆栈和goroutine信息输出到控制台,所以宕机也可以方便地知晓发生错误的位置。

    package mainfunc main() {panic("crash")}

    panic()的参数可以是任意类型,

    当panic()触发的宕机发生时,panic()后面的代码将不会被运行,但是在panic()函数前面已经运行过的defer语句依然会在宕机发生时发生作用,

    1.5 宕机恢复(recover)——防止程序崩溃

    无论是代码运行错误由Runtime层抛出的panic崩溃,还是主动触发的panic崩溃,都可以配合defer和recover实现错误捕捉和恢复,让代码在发生崩溃后允许继续运行。

    Go没有异常系统,其使用panic触发宕机类似于其他语言的抛出异常,那么recover的宕机恢复机制就对应try/catch机制。

    panic和recover的关系:

    • 有panic没recover,程序宕机。

    • 有panic也有recover捕获,程序不会宕机。执行完对应的defer后,从宕机点退出当前函数后继续执行。

    提示:虽然panic/recover能模拟其他语言的异常机制,但并不建议代表编写普通函数也经常性使用这种特性。

    2. 结构体

    结构体成员是由一系列的成员变量构成,这些成员变量也被称为“字段”。

    字段有以下特性:

    • 字段拥有自己的类型和值。

    • 字段名必须唯一。

    • 字段的类型也可以是结构体,甚至是字段所在结构体的类型。

    Go语言中没有“类”的概念,也不支持“类”的继承等面向对象的概念。

    Go语言的结构体与“类”都是复合结构体,但Go语言中结构体的内嵌配合接口比面向对象具有更高的扩展性和灵活性。

    Go语言不仅认为结构体能拥有方法,且每种自定义类型也可以拥有自己的方法。

    2.1 定义与给结构体赋值

    基本形式:

    type Point struct {X intY int}var p Pointp.X = 10p.Y = 20

    结构体的定义只是一种内存布局的描述,只有当结构体实例化时,才会真正地分配内存

    创建指针类型的结构体:

    type Player struct {name stringage int}p = new(Player)p.name = "james"p.age = 40

    取结构体的地址实例化:

    //使用结构体定义一个命令行指令(Command),指令中包含名称、变量关联和注释等type Command struct {name stringVar *intcomment string}var version int = 1cmd := &Command{}cmd.name = "version"cmd.Var = &versioncmd.comment = "show version"

    使用键值对填充结构体:

    type People struct {name stringchild *People}relation := &People{name: "爷爷"child: &People{name: "爸爸"child: &People{name: "我"},}}

    3. 方法

    Go语言中的方法(Method)是一种作用于特定类型变量的函数。这种特定类型变量叫做接收器( Receiver )。

    如果将特定类型理解为结构体或“类”时,接收器的概念就类似于其他语言中的 this 或者 self 。

    3.1 结构体方法

    创建一个背包 Bag 结构体为其定义把物品放入背包的方法 insert :

    type Bag struct {items[] int}func (b *Bag) insert(itemid int) {b.items = append(b.items, itemid)} func main() {b := new(Bag)b.insert(1001)}

    (b*Bag) 表示接收器,即 Insert 作用的对象实例。每个方法只能有一个接收器。

    3.2 接收器

    接收器是方法作用的目标

    接收器根据接收器的类型可分:

    • 指针接收器

    • 非指针接收器

    • 两种接收器在使用时会产生不同的效果。根据效果的不同,两种接收器会被用于不同性能和功能要求的代码中。

    指针接收器

    由于指针的特性,调用方法时,修改接收器指针的任意成员变量,在方法结束后,修改都是有效的。

    // 定义属性结构type Property struct {value int}// 设置属性值方法func (p *Property) setVal(val int) {p.value = val}// 获取属性值方法func (p *Property) getVal() int {return p.value}func main() {p := new(Property)p.value = 123fmt.Println(p.getVal())p.setVal(666)fmt.Println(p.getVal())}
    非指针类型接收器

    当方法作用于非指针接收器时,Go语言会在代码运行时 将接收器的值复制一份 。在非指针接收器的方法中可以获取接收器的成员值, 但修改后无效 。

    type Point struct {x, y int}func (p Point) add(other Point) Point {return Point{p.x + other.x, p.y + other.y}}func main() {// 初始化点p1 := Point{1, 1}p2 := Point{2, 2}res := p1.add(p2)fmt.Println(res)p3 := Point{3, 3}p4 := p1.add(p2).add(p3)fmt.Println(p4)}

    指针接收器和非指针接收器的使用:

    指针和非指针接收器的使用在计算机中, 小对象 由于值复制时的速度较快,所以适合使用非指针接收器。 大对象 因为复制性能较低,适合使用指针接收器,在接收器和参数间传递时不进行复制,只是传递指针。

    4. 接口

    接口是双方约定的一种合作协议。接口实现者不需要关心接口会被怎样使用,调用者也不需要关心接口的实现细节。 接口是一种类型,也是一种抽象结构,不会暴露所含数据的格式、类型及结构。

    4.1 声明接口

    type 接口类型名 interface {方法1(参数列表) 返回值...}

    Go语言的接口在命名时,一般会在单词后面添加er,如有写操作的接口叫Writer,有字符串功能的接口叫Stringer,有关闭功能的接口叫Closer等

    方法名:当方法名首字母是大写时,且这个接口类型名首字母也是大写时,这个方法可以被接口所在的包(package)之外的代码访问。

    io包中提供的Writer接口:

    type Writer interface {Write(p []type) (n int, err error)}

    4.2 实现接口

    实现接口的条件:

    • 接口的方法与实现接口的类型方法格式一致

    • 接口中所有方法均被实现

    例:为了抽象数据写入的过程,定义Data Writer接口来描述数据写入需要实现的方法。

    // 定义一个数据写入器接口type DataWriter interface {WriteData(data interface{}) error}// 定义文件结构,用于实现DataWritertype file struct {}// 实现DataWriter接口的方法func (d *file) WriteData(data interface{}) error {// 模拟写入数据fmt.Println("Write Data:", data)return nil}func main() {// 实例化filef := new(file)// 声明一个DataWriter接口var writer DataWriter// 将接口赋值,也就是*filewriter = fwriter.WriteData("one line data")}

    Go语言的接口实现是隐式的,无须让实现接口的类型写出实现了哪些接口。这个设计被称为非侵入式设计。

    “Go语言函数、结构体、方法和接口怎么用”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

    免责声明:

    ① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

    ② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

    Go语言函数、结构体、方法和接口怎么用

    下载Word文档到电脑,方便收藏和打印~

    下载Word文档

    猜你喜欢

    Go语言函数、结构体、方法和接口怎么用

    本篇内容介绍了“Go语言函数、结构体、方法和接口怎么用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1. 函数Go语言的函数属于“一等公民”
    2023-06-30

    Go语言学习函数+结构体+方法+接口

    目录1. 函数1.1 函数返回值同一种类型返回值带变量名的返回值函数中的参数传递函数变量1.2 匿名函数——没有函数名字的函数在定义时调用匿名函数将匿名函数赋值给变量匿名函数用作回调函数可变参数—&mda
    2022-06-07

    GO语言中接口和接口型函数的具体使用

    本文主要介绍了GO语言中接口和接口型函数的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-03-09

    怎么使用Go语言基础结构体

    本篇内容主要讲解“怎么使用Go语言基础结构体”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么使用Go语言基础结构体”吧!概述结构体是由一系列具有相同类型或不同类型的数据构成的数据集合语法定义结
    2023-06-25

    C语言中的结构体内嵌函数用法

    这篇文章主要介绍了C语言中的结构体内嵌函数用法,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-02-24

    GO语言中接口和接口型函数如何使用

    这篇文章主要讲解了“GO语言中接口和接口型函数如何使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“GO语言中接口和接口型函数如何使用”吧!// A Getter loads data fo
    2023-07-05

    C语言中栈的结构和函数接口的使用示例

    这篇文章主要介绍了C语言中栈的结构和函数接口的使用,类似很多软件都有撤销的操作,这其实就是用栈这种方法来实现的,当然不同的软件具体实现代码会有差异,不过原理大多都是一样的
    2023-02-14

    C语言结构体数组怎么定义和使用

    这篇文章主要讲解了“C语言结构体数组怎么定义和使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C语言结构体数组怎么定义和使用”吧!介绍一个结构体变量可以存放一个学生的一组信息,可是如果有
    2023-06-25

    C语言中队列的结构和函数接口的使用示例

    队列只允许一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO的性质;队列可用数组和链表的方法实现,使用链表的结构实现更优一些,因为如果使用数组节,出队列时删去首元素需要将整个数组前移,效率比较低
    2023-02-14

    C语言中怎么在结构体内定义函数

    这篇“C语言中怎么在结构体内定义函数”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“C语言中怎么在结构体内定义函数”文章吧。如
    2023-07-05

    C语言中的结构体和共用体怎么使用

    这篇文章主要介绍了C语言中的结构体和共用体怎么使用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C语言中的结构体和共用体怎么使用文章都会有所收获,下面我们一起来看看吧。结构体 / struct结构体的定义声明一
    2023-06-16

    Go语言-为什么返回值为接口类型,却返回结构体

    最近由于项目需求,阅读一些Go语言编写的项目的源代码,在某一个函数中发现了一个奇怪的现象:一个函数的返回值类型声明的是一个接口的类型,但是实际在函数体内返回的却是一个结构体类型的对象。 这个现象对于新手的我来说很是费解。在经过一些资料的查阅
    2022-06-07

    c语言结构体数组的用法是什么

    在C语言中,结构体数组是一种特殊的数据类型,可以用于存储和操作多个结构体对象。结构体数组由多个相同类型的结构体对象组成,每个对象可以包含多个不同类型的成员变量。使用结构体数组可以使程序更加灵活和高效。以下是一些常见的用法:定义结构体数组:
    2023-10-27

    go语言结构体初始化及赋值的方法是什么

    在Go语言中,结构体的初始化及赋值可以通过以下两种方法进行:字面量初始化:直接使用结构体类型的名称,并在花括号内指定字段的初始值。例如:type Person struct {Name stringAge int}func main()
    2023-10-25

    怎么在C语言中使用多维数组和结构体

    本篇内容介绍了“怎么在C语言中使用多维数组和结构体”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!题目:有一个颜色集合,里面有若干个颜色值(R
    2023-06-08

    编程热搜

    • Python 学习之路 - Python
      一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
      Python 学习之路 - Python
    • chatgpt的中文全称是什么
      chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
      chatgpt的中文全称是什么
    • C/C++中extern函数使用详解
    • C/C++可变参数的使用
      可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
      C/C++可变参数的使用
    • css样式文件该放在哪里
    • php中数组下标必须是连续的吗
    • Python 3 教程
      Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
      Python 3 教程
    • Python pip包管理
      一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
      Python pip包管理
    • ubuntu如何重新编译内核
    • 改善Java代码之慎用java动态编译

    目录