【Go语言】go语言简单的变量声明和结构体使用

        

目录

数字类型

布尔类型

字符串类型

Rune 类型

Byte 类型

类型转换

结构体

结构体定义

结构体作为函数参数

结构体方法

1. 接收者类型

2. 方法定义

3. 值接收者 vs 指针接收者

4. 调用方式的灵活性

5. 方法集

6. 方法与继承

7. 方法声明的位置


        在Go语言中,基础类型(也称为原始类型)是构建更复杂数据结构的基石。Go语言的基础类型可以分为几个主要类别,包括数字类型、布尔类型、和字符串类型。下面,我将为您详细介绍这些类型及其声明方法,帮助您更好地理解和使用它们。

数字类型

        在Go语言中,整数类型分为有符号和无符号,各自的范围也不同。这里给出一些整数类型的声明示例:

	var i int = 1var i8 int8 = 127var i16 int16 = 32767var i32 int32 = -2147483648var i64 int64 = 9223372036854775807var u uint = 1var u8 uint8 = 255var u16 uint16 = 65535var u32 uint32 = 4294967295var u64 uint64 = 18446744073709551615var f32 float32 = 3.1415926var f64 float64 = 3.1414926564565

 

布尔类型

        布尔类型表示逻辑值,只有truefalse两个值。

	var b bool = trueif b {fmt.Println("b 是真")} else {fmt.Println("b 是假")}

字符串类型

var s string = "Hello, Go!" // 字符串类型

Rune 类型

  rune类型代表一个Unicode码点。它是int32的别名,用于处理Unicode字符。

var r rune = '中' // 使用单引号声明rune类型,代表一个Unicode字符
fmt.Printf("%T, %d\n", r, r) // 输出: int32, 20013('中'的Unicode码点)

Byte 类型

 byte类型是uint8的别名,常用于处理ASCII字符或字节数据。

var b byte = 'A' // 使用单引号声明byte类型,代表一个ASCII字符
fmt.Printf("%T, %d\n", b, b) // 输出: uint8, 65('A'的ASCII码)

类型转换

        Go语言中的类型转换需要显式进行。这是因为Go语言在设计时强调类型安全,避免了隐式类型转换可能带来的问题。

var i int = 42
var f float64 = float64(i) // 将int类型显式转换为float64类型
var u uint = uint(f) // 将float64类型显式转换为uint类型
fmt.Println(i, f, u) // 输出: 42 42 42

结构体

结构体定义

type Person struct {name stringAge  int
}

结构体作为函数参数

type Person struct {name stringAge  int
}func testPersion(p1 Person) Person {var p Personp.name = "Alice"p.Age = 18return p
}

结构体方法

package mainimport "fmt"type Circle struct {Radius float64
}// Circle类型的方法,计算圆的面积
func (c Circle) Area() float64 {return 3.14 * c.Radius * c.Radius
}func main() {circle := Circle{Radius: 5}fmt.Println("Circle area:", circle.Area()) // 输出:Circle area: 78.5
}

1. 接收者类型

  • 值接收者:方法通过值接收其所属类型的一个副本。这意味着方法内部对接收者的任何修改都不会影响原始实例。
  • 指针接收者:方法通过指针接收其所属类型,允许直接修改原始实例的字段。使用指针接收者还可以避免在调用方法时复制大型结构体,从而提高效率。

2. 方法定义

        方法定义与函数类似,但在函数名之前添加了一个额外的参数,称为接收者,表示该方法附加到的类型。

3. 值接收者 vs 指针接收者

  • 使用值接收者定义的方法在调用时,接收者会被复制一份。这适用于小型结构体或你不希望方法能修改其接收者的场景。
  • 使用指针接收者可以让方法修改其接收者指向的值。这对于需要修改接收者,或避免在每次方法调用时复制大型结构体时非常有用。

4. 调用方式的灵活性

  • 即使方法的接收者是值类型,你也可以使用指针来调用该方法,Go语言会自动解引用。
  • 同样,如果方法的接收者是指针类型,你也可以直接使用值类型调用该方法,Go语言会自动取地址。

        这个特性使得Go语言在处理方法调用时非常灵活。下面是一个示例,展示了如何定义和使用值接收者和指针接收者的方法,以及如何通过值类型和指针类型来调用这些方法。

package mainimport "fmt"type MyStruct struct {Value int
}// 使用值接收者定义的方法
func (s MyStruct) ValueReceiverMethod() {fmt.Printf("ValueReceiverMethod 被调用, Value: %d\n", s.Value)
}// 使用指针接收者定义的方法
func (s *MyStruct) PointerReceiverMethod() {fmt.Printf("PointerReceiverMethod 被调用, Value: %d\n", s.Value)
}func main() {value := MyStruct{Value: 5}// 通过值类型调用值接收者的方法value.ValueReceiverMethod()// 通过值类型调用指针接收者的方法// Go语言自动取value的地址,使其符合方法的接收者类型value.PointerReceiverMethod()pointer := &MyStruct{Value: 10}// 通过指针类型调用值接收者的方法// Go语言自动解引用pointer,使其符合方法的接收者类型pointer.ValueReceiverMethod()// 通过指针类型调用指针接收者的方法pointer.PointerReceiverMethod()
}

        在这个示例中,MyStruct定义了两个方法:ValueReceiverMethod使用值接收者,而PointerReceiverMethod使用指针接收者。

  • ValueReceiverMethod通过结构体实例的值调用时,Go语言直接使用这个值。
  • PointerReceiverMethod通过结构体实例的值调用时,Go自动取这个值的地址,以适应方法的指针接收者。
  • 同样,当ValueReceiverMethod通过结构体的指针调用时,Go自动解引用这个指针,以适应方法的值接收者。
  • PointerReceiverMethod通过结构体的指针调用时,直接使用这个指针,因为它与方法的接收者类型匹配。

5. 方法集

  • 值类型的变量可以调用值接收者和指针接收者的方法。
  • 指针类型的变量也可以调用值接收者和指针接收者的方法。
  • 但是,接口类型的变量只能调用它的方法集内的方法。值接收者方法属于类型的值和指针的方法集,而指针接收者方法只属于类型指针的方法集

        代码定义:

package mainimport "fmt"// Shaper 接口,包含一个方法 ShapeName
type Shaper interface {ShapeName() string
}// Square 结构体
type Square struct {Name string
}// Circle 结构体
type Circle struct {Name string
}// 使用值接收者实现 Shaper 接口的 ShapeName 方法
func (s Square) ShapeName() string {return "Square: " + s.Name
}// 使用指针接收者实现 Shaper 接口的 ShapeName 方法
func (c *Circle) ShapeName() string {return "Circle: " + c.Name
}

 

 

func main() {square := Square{Name: "MySquare"}circle := Circle{Name: "MyCircle"}// 值类型的Square可以直接赋值给Shaper接口var s Shaper = squarefmt.Println(s.ShapeName())// 指针类型的Circle也可以赋值给Shaper接口var c Shaper = &circlefmt.Println(c.ShapeName())// 注意: 直接使用值类型的Circle赋值给Shaper接口会引发编译错误// var cError Shaper = circle// fmt.Println(cError.ShapeName())// 直接通过值类型调用指针接收者的方法是可以的,Go会自动取地址fmt.Println(circle.ShapeName())// 通过指针类型调用值接收者的方法也是可以的,Go会自动解引用circlePtr := &squarefmt.Println(circlePtr.ShapeName())
}
  • Square使用值接收者实现了Shaper接口的ShapeName方法,所以Square的值和指针类型都可以赋值给Shaper接口变量。
  • Circle使用指针接收者实现了Shaper接口的ShapeName方法,所以只有Circle的指针类型可以赋值给Shaper接口变量。如果尝试将Circle的值类型直接赋值给接口变量,会引发编译错误,因为Circle值类型的方法集不包括ShapeName方法。
  • 这个例子展示了如何根据方法的接收者类型(值接收者或指针接收者)以及它们如何匹配接口的方法集,来决定是否可以将一个类型的实例赋值给接口。

通过这个例子,你应该能更清楚地理解方法集和接口之间的关系,以及它们是如何影响Go语言中类型的行为的。掌握这些概念对于高效使用Go语言是非常重要的。继续探索和实践,你将能更深入地理解Go语言的面向对象特性。

 

6. 方法与继承

        Go语言没有提供传统的继承机制,但可以通过嵌入结构体来实现类似继承的效果。方法也可以通过这种方式被嵌入的结构体所继承。

        在Go语言中,虽然没有类似于传统面向对象语言的继承机制,但通过结构体的嵌入(有时也称为组合)和接口,我们可以实现类似继承的功能,包括方法的重用。这种方式提供了更灵活和更安全的代码组织形式。下面是一个示例,演示如何通过嵌入结构体来实现方法的"继承"。

        假设我们有一个Car结构体,它有一个Drive方法,然后我们希望ElectricCar结构体“继承”Car的方法。

package mainimport "fmt"// Car 基础结构体
type Car struct {Name string
}// Car的Drive方法
func (c Car) Drive() {fmt.Println(c.Name, "is driving.")
}// ElectricCar 嵌入了Car
type ElectricCar struct {Car   // 嵌入Car结构体BatteryLife int
}func main() {eCar := ElectricCar{Car:        Car{Name: "Tesla Model S"},BatteryLife: 300,}// 通过ElectricCar直接调用Car的Drive方法eCar.Drive()// 也可以通过嵌入的Car结构体字段调用eCar.Car.Drive()// 访问ElectricCar的字段fmt.Println("Battery life:", eCar.BatteryLife)// 访问嵌入的Car结构体的字段fmt.Println("Car name:", eCar.Name) // 直接访问,Go自动解析到eCar.Car.Namefmt.Println("Car name:", eCar.Car.Name) // 显式访问
}
  • ElectricCar通过嵌入Car结构体,"继承"了Car的方法和属性。这意味着,即使没有显式定义Drive方法,ElectricCar的实例也能调用Drive方法。
  • 通过这种嵌入机制,我们可以很容易地重用Car的功能,同时为ElectricCar添加特有的属性和方法,例如BatteryLife属性。
  • 你可以通过嵌入结构体的实例直接访问其公开的字段和方法,就像它们是外层结构体的一部分一样。在上面的示例中,eCar.Name实际上是对eCar.Car.Name的访问简写。
  • 如果需要,嵌入的结构体也可以被显式地引用,如eCar.Car.Drive()

这种方式允许Go语言开发者在没有传统类继承的情况下实现非常灵活的类型设计。通过组合和接口,你可以构建出清晰、易于理解和维护的代码结构。这种方法强调的是,“有什么”(组合)而不是“是什么”(继承),更加注重对象的能力而非其身份。继续探索Go的类型系统,你会发现更多有趣且实用的设计模式。

7. 方法声明的位置

        方法可以在类型定义内部或外部声明,但是接收者的类型必须在同一个包内。这意味着你不能为内置类型或来自其他包的类型定义方法。

为自定义类型声明方法

package mainimport "fmt"// 在main包中定义了一个简单的结构体类型Person
type Person struct {Name string
}// 为Person类型声明一个方法SayHello,这是允许的,因为Person在同一个包内定义
func (p Person) SayHello() {fmt.Println("Hello,", p.Name)
}func main() {person := Person{Name: "张三"}person.SayHello() // 调用SayHello方法
}

        在这个例子中,Person类型和它的方法SayHello都是在main包中定义的。这完全符合Go语言的规则。

尝试为内置类型或其他包的类型添加方法

        假设我们想为内置的int类型添加一个新方法。尝试这样做会遇到编译错误,因为int是一个内置类型,不在用户自定义的包中。

func (i int) IsPositive() bool {return i > 0
}

        同样地,如果你试图为来自其他包的类型定义方法,也会遇到问题。例如,尝试为time.Time类型(定义在time包中)添加一个方法:

package mainimport ("fmt""time"
)// 尝试为time包中的Time类型添加一个新方法Display
func (t time.Time) Display() {fmt.Println("The time is:", t)
}func main() {now := time.Now()now.Display() // 这里会引发编译错误
}

 

        上述代码尝试为time.Time类型添加一个Display方法。因为Time类型定义在time包中,而不是当前的包(即使是main包),所以这将导致编译错误。

        这些限制确保了Go语言包的封装性和独立性,防止了对已有类型的随意扩展,促进了代码的清晰性和维护性。要为其他包中的类型添加新的行为,通常的做法是在你自己的包中定义一个新的类型,这个新类型可以嵌入原有类型或者作为原有类型的一个字段存在。

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

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

相关文章

【Linux】sudo分权管理实战

一般sudo命令是默认安装的,如果你的机器里没有,可以使用命令 yum install sudo 来安装 [rootgaosh-64 ~]# yum install sudo 我们来看一下配置文件: 在上图root下面添加一行 ,给gaosh用户加权限 [rootgaosh-64 ~]# vim /etc/su…

中移物联网 OneOS 操作系统环境搭建和工程创建

一、官网 OneOS Lite是中国移动针对物联网领域推出的轻量级操作系统,具有可裁剪、跨平台、低功耗、高安全等特点,支持ARM Cortex-A和 Cortex-M、MIPS、RISC-V等主流芯片架构,兼容POSIX、CMSIS等标准接口,支持Javascript、MicroPyt…

nvm安装详细教程(安装nvm、node、npm、cnpm、yarn及环境变量配置)

一、安装nvm 1. 下载nvm 点击 网盘下载 进行下载 2、双击下载好的 nvm-1.1.12-setup.zip 文件 3.双击 nvm-setup.exe 开始安装 4. 选择我接受,然后点击next 5.选择nvm安装路径,路径名称不要有空格,然后点击next 6.node.js安装路径&#…

哨兵-1A与DInSAR技术监测尼泊尔地震前后地表形变

2015年4月25号,尼泊尔发生里氏7.8级地震,超过5000人伤亡和几百万人受到影响。大量的卫星影像支持地震救援。地理学家利用卫星影像量测地震对陆地的影响。 Sentinel-1A是欧洲委员会发起的哥白尼环境监测计划中的第一颗卫星。可获取全天候的数据&#xff0…

实验6 单臂路由方式实现VLAN间路由

实验6 单臂路由方式实现VLAN间路由 一、 原理描述二、 实验目的三、 实验内容四、 实验配置五、 实验步骤1.配置IP地址2.交换机配置3.路由器配置 一、 原理描述 VLAN将一个物理的LAN在逻辑上划分为多个广播域。VLAN内的主机间可以互相通信,但是VLAN之间却不能互通。…

JAVAEE——网络初始

文章目录 网络发展史独立模式网络模式局域网LAN路由器的诞生 网络通信的基础IP地址端口号 认识协议OSI七层模型TCP/IP五层模型 网络发展史 独立模式 在原始的年代中电脑间想要通信需要两台电脑连接一根网线,但是一台电脑基本上只有一个接口。因此想要链接更多的电…

ChatGPT 写作秘籍:指导您如何利用ChatGPT撰写学术论文

ChatGPT无限次数:点击直达 ChatGPT 写作秘籍:指导您如何利用ChatGPT撰写学术论文 作为CSDN网站的作者,您可能经常面临不同类型的写作任务,包括学术论文的撰写。在这篇文章中,我们将探讨如何利用ChatGPT这一强大的文本生成工具来辅…

计算机基础知识-第9章-存储的本质(2)——硬盘和文件系统基础知识

一、机械硬盘的原理 概括来说,硬盘的工作原理是利用特定的磁粒子的极性来记录数据。磁头在读取数据时,将磁力子的不同极性转换成不同的电脉冲信号,再利用数据转换器将这些原始信号变成电脑可以使用的数据,写的操作正好与此相反。…

ubuntu或类Debian获取某些包的离线版本-包括依赖(还有一些意想不到的用途,哈哈)

前言 偶尔能碰到很特殊的情况。网址白名单,纯内网,超多依赖及一些很难描述的场景。 比如一些少见的发行版缺少某些包。这时候可以找一台类似的系统环境来下载离线包及 其依赖包,然后转移到内网进行安装。如果是网址白名单,或者纯内…

【讲解下常见的分类算法】

🎥博主:程序员不想YY啊 💫CSDN优质创作者,CSDN实力新星,CSDN博客专家 🤗点赞🎈收藏⭐再看💫养成习惯 ✨希望本文对您有所裨益,如有不足之处,欢迎在评论区提出…

牛客NC413 两个升序数组的中位数【hard 数组,模拟 Java、Go、PHP】

题目 题目链接: https://www.nowcoder.com/practice/b3b59248e61f499482eaba636305474b 思路 直接模拟2个数组有顺序放到一个数组中help中如果help长度为奇数,返回中间的数如果help长度为偶数,返回中间2个数的和除以2参考答案java import j…

【AI 测试】八:数学基础在算法测试工程师工作中的具体应用

算法测试工程师在测试和优化算法时,确实需要具备扎实的数学基础。这是因为算法往往涉及到复杂的计算、逻辑推理和数据分析,而这些都需要依靠数学工具和方法来进行有效的处理。以下是数学基础在算法测试工程师工作中的具体应用: 线性代数&…

会话跟踪技术基础:Cookie和Session

久违了,之前忙碌了一周赶毕设,今天抽空更新~ 一.理论知识 1.会话:用户打开浏览器,访问web服务器的资源,会话建立,直到有一方断开连接,会话结束。在一次会话中可以包含多次请求和响应~ 2.会话跟…

【远程桌面】Microsoft Remote Desktop 4 mac

看起来 mac的apple store 不给下载mac apple store 微软官方可以直接下载 app center 最新版本。 官方文档 这里有更新的介绍和下载地址

Python生成图片和音频验证码

captcha是pyhton的一个模块,用来生成图片和音频验证码。 安装 pip install captcha使用 from captcha.audio import AudioCaptcha from captcha.image import ImageCaptcha# 加载声音和字体 audio AudioCaptcha(voicedir/path/to/voices) image ImageCaptcha(…

StylizedGS: Controllable Stylization for 3D Gaussian Splatting

StylizedGS: Controllable Stylization for 3D Gaussian Splatting StylizedGS:3D高斯溅射的可控样式化 Dingxi Zhang, Zhuoxun Chen, Yu-Jie Yuan, Fang-Lue Zhang, Zhenliang He, Shiguang Shan, and Lin Gao1 张定西,陈卓勋,袁玉洁&#x…

vue3.4 新特性 defineModel() 宏

v-model 简介 官网是这样解释 v-model 的 v-model 的功能是&#xff0c;实现数据的双向绑定【本质上是 :value 和 input 语法糖】 如果是表单元素&#xff0c;下面两种写法是一样&#xff0c;这时v-model就是语法糖&#xff0c;帮你简化了操作 <input v-model"messag…

【MySQL】锁篇

SueWakeup 个人主页&#xff1a;SueWakeup 系列专栏&#xff1a;学习技术栈 个性签名&#xff1a;保留赤子之心也许是种幸运吧 本文封面由 凯楠&#x1f4f8;友情提供 目录 本系列专栏 1. MySQ 中的锁 2. 表锁和行锁 表锁 行锁 3. InnoDB 存储引擎的三种行级锁 4. 悲观锁…

文心一言 VS 讯飞星火 VS chatgpt (234)-- 算法导论17.2 2题

二、用核算法重做练习17.1-3。练习17.1-3的内容是&#xff1a;假定我们对一个数据结构执行一个由 n 个操作组成的操作序列&#xff0c;当 i 严格为 2 的幂时第 i 个操作的代价为 i &#xff0c;否则代价为1。使用聚合分析确定每个操作的摊还代价。 文心一言&#xff1a; 练习…

读《敏捷营销》 策略执行(五)

前言 在看到策略执行时&#xff0c;实际上对我的影响在于就是对以前知识的归纳总结&#xff0c;但也有二个很强的观点吸引了我&#xff0c;一是琳达误谬&#xff0c;蒙特卡洛误谬&#xff1b;二是避免噪声和群体偏见。如果我们在制定方案或策略时&#xff0c;犯了这种错&#x…