Golang基础语法(go语言指针、go语言方法、go语言接口)

文章目录

  • go语言指针
    • 什么是指针
    • 创建指针
      • new() 函数
  • go语言方法
    • 方法的定义​
    • 方法的调用
    • 继承
      • 隐式继承 vs 显式继承
  • go语言接口
  • 什么是接口
  • 接口定义
    • 接口里装的是“一个具体值”,phone.(Apple) 取出来的也是“这个值的拷贝”,改它不会改回接口里那份;而用指针时,接口里装的是地址,你改的是同一块内存。
      • 1)phone = Apple{}:接口里装的是一个“Apple 值”
      • 2)为什么 phone.(Apple).PhoneName = "Apple" 直接写还不行?
  • 实现多个接口
  • 空接口
  • 断言
  • 接口作函数参数
  • 接口嵌套

go语言指针

什么是指针

像C语言一样,go语言也有指针的概念。简单理解,指针就是地址,指针变量就是存放地址的变量。在一个变量前加上*,那么这个变量就是指针变量,指针变量只能存放地址。

1个指针变量可以指向任何一个值的内存地址,它所指向的值的内存地址在 32 和 64 位机器上分别占用 4 或 8 个字节,占用字节的大小与所指向的值的大小无关。

创建指针

声明指针

我们可以像声明其它类型的变量一样,声明一个指针变量

vara*int

上述方法声明了一个整形指针变量a,但是该变量还没有存放任何地址,操作系统并未为其指向的内容分配内存,即该指针没有指向任何内容,所以它是一个空指针。

varbint=3a=&b

此时不再是一个空指针,a指向一个整型变量,该变量的值是3。
要获取指针变量所指向的内容,很简单,在变量前加*即可

代码展示:

packagemainimport"fmt"funcmain(){vara*intfmt.Printf("赋值前a:%v\n",a)varbint=3a=&b// a存放的是b的地址fmt.Printf("赋值后a:%v\n",a)// 打印出的地址fmt.Printf("a指向的内容是:%v\n",*a)// *a表示a存放的地址对应的内存存放的内容,这里为整数3}

运行结果:

赋值前a:<nil>赋值后a:0xc00001c040 a指向的内容是:3

new() 函数

Go语言还提供了另外一种方法来创建指针变量,使用new函数创建

new(type)

代码展示:

packagemainimport"fmt"funcmain(){s:=new(string)fmt.Printf("赋值前s:%v\n",s)fmt.Printf("赋值前s的内容:%v\n",*s)*s="Golang学习之路"fmt.Printf("赋值后s:%v\n",s)fmt.Printf("赋值后s的内容:%v\n",*s)}

运行结果:

赋值前s:0xc00009e210 赋值前s的内容: 赋值后s:0xc00009e210 赋值后s的内容:Golang学习之路

可以看到,通过new函数创建指针的时候,系统会为其分配内存,所以两次都能打印出地址,但是,在没有对其赋值的时候,系统会存放默认值,string类型的就是空字符串""。

go语言方法

方法的定义​

方法是一类特殊的函数,方法是绑定在某种类型的变量上的函数,它有一定的约束范围。而变量的类型不仅仅局限于结构体类型,可以是任意类型,比如int、bool等的别名类型。​

有过c++或者java基础的同学可以这样理解,一个struct加上绑定在这个类型上的方法就等价于一个类。​

方法的定义格式如下

func(recv recv_type)methodName(paramr_list)(return_val_list){...}

对比前面我们学习过的函数,方法跟函数的唯一区别就是在func关键字和函数名之间加了一个接收者类型和接收者,同样,这个接收者的类型可以是普通变量或者指针变量​

方法的调用跟结构体属性的调用方式相同,都是通过 . 操作符来完成​

下面给Student结构定义一个方法

packagemainimport"fmt"typeStudentstruct{IDintNamestringAgeintScoreint}func(st*Student)GetName()string{returnst.Name}funcmain(){st:=&Student{ID:100,Name:"zhangsan",Age:18,Score:98,}fmt.Printf("学生st的姓名是:%s\n",st.GetName())// 调用Student的方法GetName}

运行结果:

学生st的姓名是: zhangsan

注意:在 go语言中,类型的定义和绑定在它上面的方法的定义可以不放置在同一个文件中,它们可以存在在不同的源文件唯一的要求是:它们必须在同一个包下面

方法的调用

定义在指针类型或者值类型上的方法可以通过指针变量或者值变量来调用,可能读起来有点绕,下面看例子,会更清晰

packagemainimport"fmt"typeStudentstruct{IDintNamestringAgeintScoreint}func(st*Student)SetScore(scoreint){st.Score=score}func(st Student)GetScore()int{returnst.Score}funcmain(){st:=&Student{ID:100,Name:"zhangsan",Age:18,Score:98,}fmt.Printf("设置前, 学生st的分数是:%d\n",st.GetScore())// 通过指针调用定义在值类型的方法GetScorest.SetScore(100)// 通过指针调用定义在指针类型上的方法fmt.Printf("设置后, 学生st的分数是:%d\n",st.GetScore())// 通过指针调用定义在值类型的方法GetScore}

运行结果:

设置前, 学生st的分数是:98 设置后, 学生st的分数是:100

继承

go语言不像c++或者java一样有显示的继承关系,因为go语言没有类的概念,所以自然就不存在父类、子类一说,自然就没有继承的关系。那么,go语言是如何实现功能的呢?

答案是组合,go语言中不论是属性,还是方法的继承都是通过组合来实现的

请看下面例子

typePeoplestruct{NamestringAgeint}typeStudentstruct{IDintScoreintPeople// 将People作为Student的一个属性,注意不要加变量名,这就是隐式继承}

隐式继承 vs 显式继承


将原来Student的定义改为Student 和People 两个结构来定义,通过这种组合的方式,其实Student 就拥有了 People的Name属性和Age属性

packagemainimport"fmt"typePeoplestruct{NamestringAgeint}func(p*People)GetName()string{returnp.Name}typeStudentstruct{IDintScoreintPeople// 将People作为Student的一个属性,注意不要加变量名,这就是隐式继承}func(st*Student)SetScore(scoreint){st.Score=score}func(st Student)GetScore()int{returnst.Score}funcmain(){st:=&Student{ID:100,Score:98,People:People{Name:"zhangsan",Age:18,},}fmt.Printf("学生st的分数是:%d\n",st.GetScore())fmt.Printf("学生st的姓名是:%s\n",st.GetName())}

运行结果:

学生st的分数是:98 学生st的姓名是:zhangsan

这个例子中,Student 通过内嵌People获得了People的Name和Age属性以及GetName方法。

go语言接口

什么是接口

go语言中的接口很简单,就是一组方法的声明。当某一种类型实现了所有这些声明的方法,那么就称这种类型为该接口的一种实现。

接口定义

go语言中同样用关键字 interface 来定义接口

typeinterfaceNameinterface{methodName1([parameter_list])[return_type_list]methodName2([parameter_list])[return_type_list]methodName3([parameter_list])[return_type_list]...}

下面看一个具体的interface的例子

packagemainimport"fmt"typePhoneinterface{Call()SendMessage()}typeApplestruct{PhoneNamestring}func(a Apple)Call(){fmt.Printf("%s有打电话功能\n",a.PhoneName)}func(a Apple)SendMessage(){fmt.Printf("%s有发短信功能\n",a.PhoneName)}typeHuaWeistruct{PhoneNamestring}func(h HuaWei)Call(){fmt.Printf("%s有打电话功能\n",h.PhoneName)}func(h HuaWei)SendMessage(){fmt.Printf("%s有发短信功能\n",h.PhoneName)}funcmain(){a:=Apple{"apple"}b:=HuaWei{"huawei"}a.Call()a.SendMessage()b.Call()b.SendMessage()varphone Phone// 声明一个接口类型phonephone=new(Apple)// 注意这种创建方式,new函数参数是接口的实现phone.(*Apple).PhoneName="Apple"// 这里使用断言给phone的成员赋值,后面会讲到接口的断言phone.Call()phone.SendMessage()}

运行结果:

apple有打电话功能 apple有发短信功能 huawei有打电话功能 huawei有发短信功能 Apple有打电话功能 Apple有发短信功能

上述声明了一个phone的接口,有两个方法Call()和Sendmessage(),然后定义了两个结构Apple和HuaWei,这两个结构都实现了Phone接口定义的所有方法,但是实现的方法不同,所以Apple和HuaWei是Phone接口的两种实现

注意:上述例子的phone变量的定义,首先声明phone为一个接口,接着用new方法为这个phone定义,注意,这里new的参数必须是phone的一种实现,假设这里Apple结构没有实现SendMessage方法,那么Apple结构就不是Phone接口的一个实现,上述代码的45行用new定义phone的时候就会报错。

接口里装的是“一个具体值”,phone.(Apple) 取出来的也是“这个值的拷贝”,改它不会改回接口里那份;而用指针时,接口里装的是地址,你改的是同一块内存。

1)phone = Apple{}:接口里装的是一个“Apple 值”

varphone Phone phone=Apple{PhoneName:"old"}// 接口内部保存:动态类型=Apple,动态值=一份 Apple 的拷贝

这时做断言:

a:=phone.(Apple)// a 得到的是“接口里那份 Apple 值”的拷贝a.PhoneName="Apple"

2)为什么 phone.(Apple).PhoneName = “Apple” 直接写还不行?

因为 phone.(Apple) 得到的是一个非地址的临时值(不可寻址),Go 不允许对“不可寻址的值”直接改字段:

phone.(Apple).PhoneName="Apple"// 编译报错:cannot assign to struct field ... in map / not addressable 之类

你必须先接出来到变量里(但接出来仍是拷贝):

tmp:=phone.(Apple)tmp.PhoneName="Apple"// 只改 tmpphone=tmp// 想让接口里的值变,必须再塞回去


实现多个接口

有上述接口的定义我们知道,类型可以实现接口,那么一种类型可以实现多个接口吗,答案是:可以的。

请看下面例子:

packagemainimport"fmt"typeMyWriterinterface{MyWriter(sstring)}typeMyReadinterface{MyReader()}typeMyWriteReaderstruct{}func(r MyWriteReader)MyWriter(sstring){fmt.Printf("call MyWriteReader MyWriter %s\n",s)}func(r MyWriteReader)MyReader(){fmt.Printf("call MyWriteReader MyReader\n")}funcmain(){varmyRead MyRead myRead=new(MyWriteReader)myRead.MyReader()varmyWriter MyWriter myWriter=MyWriteReader{}myWriter.MyWriter("hello")}

运行结果:

call MyWriteReader MyReader call MyWriteReader MyWriter hello

上述例子我们定义了一个 MyWriter 接口,该接口有一个方法 MyWriter 方法接受一个 string 类型的参数。接着,我们定义了一个 MyReader 接口,该接口有一个方法 MyReader。然后定义了一个 ReadWriter结构,实现了接口 MyWriter 和接口 MyReader 中的所有方法,所以ReadWriter分别实现了两个不同的接口MyWriter和MyReader。

空接口

没有任何方法声明的接口称之为空接口,interface{}

所有的类型都实现了空接口,因此空接口可以存储任意类型的数值

Golang 很多库的源代码都会以空接口作为参数,表示接受任意类型的参数,比如 fmt 包下的 Print 系列函数

funcPrintln(a...interface{})(nint,errerror)funcPrint(a...interface{})(nint,errerror)

看下面例子:

packagemainimport("fmt")funcmain(){varanyinterface{}any=10fmt.Println(any)any="golang"fmt.Println(any)any=truefmt.Println(any)}

运行结果:

10golangtrue

上述例子首先声明了一个空接口any,首先用来存储整形变量10,然后又用来存储字符串golang,最后用来存储布尔型变量true,所以空接口可以存储任意类型的数值fmt.Println函数的参数是空接口类型interface{},所以能将结果正确打印出来。

断言

在介绍断言之前,先看一个例子

packagemainfuncmain(){varaint=1variinterface{}=avarbint=i}

运行结果:

./prog.go:6:14: cannot use i(variable oftypeinterface{})astypeintinvariable declaration:​ needtypeassertion

编译报错,不能将interface{}类型的变量i赋值给整型变量b​

所以在写代码的时候我们需要注意,可以将任意类型的变量赋值给空接口interface{}类型,但是反过来不行。​

那为了让这个操作能够完成,我们需要怎么做呢?就是断言​

类型断言(Type Assertion)接口操作,用来检查接口变量的值是否实现了某个接口或者是否是某个具体的类型​

断言的一般格式为:

value,ok:=x.(T)// x为接口类型,ok为bool类型
  • T 是具体某个类型,类型断言会检查 x 的动态类型是否等于具体类型 T。如果检查成功,类型断言返回的结果是 x 的值,其类型是 T。​
  • x 是接口类型,类型断言会检查 x 的动态类型是否满足 T。如果检查成功,返回值是一个类型为 T 的接口值。​
  • 无论 T 是什么类型,如果 x 是 nil 接口值,类型断言都会失败。​

请看下面例子:

packagemainimport("fmt")funcmain(){varxinterface{}x=8val,ok:=x.(int)fmt.Printf("val is %d, ok is %t\n",val,ok)}

运行结果:

val is8, ok istrue

注意:如果在断言的过程中,没有 bool 这个值的判断,如果断言成功程序正常运行,假设 interface{} 存储的值跟要断言的类型不一致,则程序会报 panic。

看下面例子:

packagemainimport("fmt")funcmain(){varxinterface{}x="golang"val:=x.(int)fmt.Println(val)}

运行结果

panic:interfaceconversion:interface{}isstring,notint

接口作函数参数

接口做函数参数,在函数定义的时候,形参为接口类型,在函数调用的时候,实参为该接口的具体实现

具体看下面例子:

packagemainimport"fmt"typeReaderinterface{Read()int}typeMyReaderstruct{a,bint}func(m*MyReader)Read()int{returnm.a+m.b}funcDoJob(r Reader){fmt.Printf("myReader is %d\n",r.Read())}funcmain(){myReader:=&MyReader{2,5}DoJob(myReader)}

运行结果:

myReader is7

若函数的形参为空接口,则实参可以为任意类型,因为空接口没有定义任何方法,任意类型都是空接口的一种实现

packagemainimport"fmt"funcDoJob(valueinterface{}){fmt.Printf("value is %v\n",value)}funcmain(){val:=10DoJob(val)}

运行结果:

value is10

接口嵌套

接口嵌套就是一个接口中包含了其他接口,如果要实现外部接口,则需要实现内部嵌套的接口对应的所有方法。

看具体例子:

packagemainimport"fmt"typeAinterface{run1()}typeBinterface{run2()}// 定义嵌套接口CtypeCinterface{A Brun3()}typeRunnerstruct{}// 实现嵌套接口A的方法func(r Runner)run1(){fmt.Println("run1!!!!")}// 实现嵌套接口B的方法func(r Runner)run2(){fmt.Println("run2!!!!")}func(r Runner)run3(){fmt.Println("run3!!!!")}funcmain(){varrunner C runner=new(Runner)// runner实现了C接口的所有方法runner.run1()runner.run2()runner.run3()}

运行结果:

run1!!!!run2!!!!run3!!!!

之后我会持续更新,如果喜欢我的文章,请记得一键三连哦,点赞关注收藏,你的每一个赞每一份关注每一次收藏都将是我前进路上的无限动力 !!!↖(▔▽▔)↗感谢支持!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1130613.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Z-Image-Turbo图生图实战:快速搭建图像转换工作流

Z-Image-Turbo图生图实战&#xff1a;快速搭建图像转换工作流 作为一名设计师&#xff0c;你是否曾经被复杂的AI图像生成参数和工作流程困扰&#xff1f;Z-Image-Turbo的出现彻底改变了这一局面。这款由阿里巴巴开源的图像生成模型&#xff0c;仅需6B参数就能实现1秒出图&#…

从学术到工业:M2FP模型的商业化应用之路

从学术到工业&#xff1a;M2FP模型的商业化应用之路 &#x1f9e9; M2FP 多人人体解析服务&#xff1a;技术落地的关键一步 在计算机视觉领域&#xff0c;人体解析&#xff08;Human Parsing&#xff09; 是一项极具挑战性的任务——它要求模型不仅识别出图像中的人体位置&…

*存取控制矩阵** - 是一种以二维矩阵形式表示权限的模型,行代表用户,列代表文件,矩阵中的每个元素表示某用户对某文件的访问权限

一、文件存取控制方法存取控制矩阵 是一种以二维矩阵形式表示权限的模型&#xff0c;行代表用户&#xff0c;列代表文件&#xff0c;矩阵中的每个元素表示某用户对某文件的访问权限&#xff08;如读、写、执行&#xff09;。优点&#xff1a;概念直观清晰。缺点&#xff1a;当系…

GEO搜索优化系统开发全指南:技术选型+源码实现+精准获客落地方案

随着本地生活、跨境电商等行业对“地域精准获客”需求的爆发&#xff0c;GEO搜索优化系统已成为企业突破流量瓶颈的核心技术载体。不同于传统SEO的泛流量收割&#xff0c;GEO系统基于地理定位与语义理解技术&#xff0c;实现“用户地域需求→精准内容匹配→高效转化”的全链路闭…

无需GPU!纯CPU环境运行高性能翻译模型的秘诀

无需GPU&#xff01;纯CPU环境运行高性能翻译模型的秘诀 &#x1f310; AI 智能中英翻译服务 (WebUI API) 在当前AI大模型主导的翻译领域&#xff0c;大多数高质量神经网络翻译系统都依赖于强大的GPU算力支持。然而&#xff0c;在实际开发与部署场景中&#xff0c;并非所有用户…

M2FP模型部署成本分析:CPU与GPU方案对比

M2FP模型部署成本分析&#xff1a;CPU与GPU方案对比 &#x1f4cc; 引言&#xff1a;为何需要多人人体解析服务&#xff1f; 在智能安防、虚拟试衣、人机交互和视频内容分析等场景中&#xff0c;精准的人体语义分割已成为关键技术支撑。传统的图像分割方法往往难以应对多目标重…

2026年多语言AI趋势:开源翻译镜像+WebUI成中小企业首选

2026年多语言AI趋势&#xff1a;开源翻译镜像WebUI成中小企业首选 &#x1f310; AI 智能中英翻译服务 (WebUI API) &#x1f4d6; 项目简介 随着全球化进程加速&#xff0c;跨语言沟通已成为企业日常运营的重要组成部分。尤其在跨境电商、国际协作与内容出海等场景下&…

基于M2FP的虚拟服装店:3D试衣体验实现

基于M2FP的虚拟服装店&#xff1a;3D试衣体验实现 &#x1f9e9; M2FP 多人人体解析服务&#xff1a;构建智能试衣间的核心引擎 在虚拟现实与电商融合的浪潮中&#xff0c;3D虚拟试衣正成为提升用户体验的关键技术。传统试衣流程受限于物理空间和商品库存&#xff0c;而数字化解…

**脱机控制**:用户无需直接参与作业运行过程,而是通过**作业控制语言(JCL)**编写作业说明书

上述内容系统地描述了操作系统中作业控制与管理的核心概念&#xff0c;具体解析如下&#xff1a; 一、作业控制 脱机控制&#xff1a;用户无需直接参与作业运行过程&#xff0c;而是通过**作业控制语言&#xff08;JCL&#xff09;**编写作业说明书&#xff0c;系统依据说明书自…

M2FP模型在智慧医疗影像分析中的突破

M2FP模型在智慧医疗影像分析中的突破 &#x1f9e9; M2FP 多人人体解析服务&#xff1a;技术背景与行业价值 在智慧医疗快速发展的今天&#xff0c;医学影像分析正从“辅助诊断”迈向“精准理解”的新阶段。传统图像识别技术多聚焦于病灶检测或器官定位&#xff0c;而对人体整…

本地化部署 vs SaaS服务:TCO成本对比分析(三年周期)

本地化部署 vs SaaS服务&#xff1a;TCO成本对比分析&#xff08;三年周期&#xff09; 随着人工智能技术的普及&#xff0c;企业对高质量翻译服务的需求日益增长。在构建多语言能力时&#xff0c;一个关键决策是选择本地化部署的AI翻译系统&#xff0c;还是依赖第三方SaaS翻译…

M2FP模型在智能广告牌中的人体互动应用

M2FP模型在智能广告牌中的人体互动应用 &#x1f9e9; M2FP 多人人体解析服务&#xff1a;技术核心与场景价值 在智能交互系统快速演进的今天&#xff0c;人体语义解析正成为连接物理世界与数字内容的关键桥梁。尤其是在智能广告牌、互动展厅、虚拟试衣等前沿场景中&#xff0c…

医疗文本翻译挑战:CSANMT专业词汇准确率达88%

医疗文本翻译挑战&#xff1a;CSANMT专业词汇准确率达88% &#x1f4cc; 引言&#xff1a;AI 智能中英翻译服务的现实需求 随着全球医疗合作日益紧密&#xff0c;医学文献、临床报告和药品说明书的跨语言交流成为刚需。然而&#xff0c;通用机器翻译系统在面对高度专业化、术语…

M2FP模型在虚拟服装展示中的核心技术

M2FP模型在虚拟服装展示中的核心技术 &#x1f9e9; M2FP 多人人体解析服务&#xff1a;构建智能虚拟试衣的视觉基石 在虚拟服装展示与在线试衣间等应用场景中&#xff0c;精准的人体语义分割是实现“所见即所得”体验的核心前提。传统图像处理方法难以应对多人、遮挡、姿态多变…

对比测试:百度翻译 vs 开源CSANMT,谁更适合私有化部署

对比测试&#xff1a;百度翻译 vs 开源CSANMT&#xff0c;谁更适合私有化部署 &#x1f4d6; 背景与需求&#xff1a;AI 智能中英翻译服务的落地挑战 在企业级应用中&#xff0c;高质量的中英智能翻译服务已成为跨国协作、内容本地化和知识管理的关键基础设施。面对日益增长的…

M2FP模型架构解析:Mask2Former的改进与创新

M2FP模型架构解析&#xff1a;Mask2Former的改进与创新 &#x1f4cc; 引言&#xff1a;从语义分割到精细化人体解析 随着计算机视觉技术的发展&#xff0c;语义分割已从基础场景理解逐步迈向细粒度目标解析。在众多细分任务中&#xff0c;多人人体解析&#xff08;Human Parsi…

进程同步互斥

试题 1试题正文今有3个并发进程R、M、P&#xff0c;它们共享一个缓冲器B。今有3个并发进程R、M、P&#xff0c;它们共享一个缓冲器B。进程R负责向B中输入数据&#xff08;整数&#xff09;&#xff1b;如果进程R送入的数据是偶数&#xff0c;进程M负责打印&#xff1b;如果进程…

M2FP模型异常检测与处理

M2FP模型异常检测与处理&#xff1a;多人人体解析服务的稳定性优化实践 &#x1f4d6; 项目背景与核心挑战 在计算机视觉领域&#xff0c;多人人体解析&#xff08;Human Parsing&#xff09; 是一项关键任务&#xff0c;旨在对图像中每个个体的身体部位进行像素级语义分割。相…

M2FP在智能健身镜中的应用:姿势矫正

M2FP在智能健身镜中的应用&#xff1a;姿势矫正 引言&#xff1a;智能健身的视觉革命 随着居家健身和AI健康管理的兴起&#xff0c;智能健身镜作为融合运动科学与人工智能的终端设备&#xff0c;正逐步进入家庭和健身房。其核心能力之一是实时姿态识别与动作指导&#xff0c;…

M2FP模型在VR虚拟形象创建中的关键作用

M2FP模型在VR虚拟形象创建中的关键作用 &#x1f9e9; M2FP 多人人体解析服务&#xff1a;构建高精度虚拟形象的基石 在虚拟现实&#xff08;VR&#xff09;内容生态中&#xff0c;高保真、个性化的虚拟形象&#xff08;Avatar&#xff09;是提升用户沉浸感与社交体验的核心要…