100天精通Golang(基础入门篇)——第19天:深入剖析Go语言中方法(Method)的妙用与实践

news2025/1/20 20:05:38

在这里插入图片描述

🌷🍁 博主猫头虎 带您 Go to Golang Language.✨✨🍁
🦄 博客首页——猫头虎的博客🎐
🐳《面试题大全专栏》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺
🌊 《IDEA开发秘籍专栏》学会IDEA常用操作,工作效率翻倍~💐
🌊 《100天精通Golang(基础入门篇)》学会Golang语言,畅玩云原生,走遍大小厂~💐

🪁🍁 希望本文能够给您带来一定的帮助🌸文章粗浅,敬请批评指正!🍁🐥

100天精通Golang(基础入门篇)

  • 方法
      • 摘要 📝
      • 引言 🎙️
      • 导语 🗺️
    • 1.1 什么是方法
    • 1.2 方法的语法
    • 1.3 方法和函数
    • 1.4 变量作用域
    • 1.5 method继承
    • 1.6 method重写
    • 1.7 接口与方法
    • 1.8 方法的签名
    • 1.9 方法值和方法表达式
      • 方法值
      • 方法表达式
    • 1.10 方法的可见性
      • 总结🌟
      • 参考资料
  • 结语

方法

深入剖析Go语言:第19天专注方法(Method)的妙用与实践

摘要 📝

掌握Go语言的方法(Method)🛠️不仅能让你的代码更加有序✅,也能实现更多功能🚀和更高的可维护性🔧。本篇博客是我们"100天精通Golang"系列📚的第19篇,将深入解释Go中方法的语法📖、用法🤔、作用范围🌐以及与函数的区别🔄等。

引言 🎙️

你好,亲爱的读者👋,我是猫头虎博主😺🐅!Go语言因其简洁🗂️、高效⚡而日益受到开发者的喜爱💖。然而,要想充分利用Go语言的强大功能💪,理解其方法(Method)的概念🧠是非常必要的。在本篇博客中,我们将一同探讨Go语言中的方法概念🕵️‍♀️,看看它是如何使我们的编程生活变得更美好😊。

导语 🗺️

本篇博文将覆盖以下几个方面📋:

1️⃣ 方法的基本语法和定义方式📐
2️⃣ 值接收者和指针接收者的区别🔍
3️⃣ 方法与函数的对比📊
4️⃣ 局部变量和全局变量在方法中的应用📍
5️⃣ 方法的继承与重写🔄

无论你是Go语言的新手👶还是有经验的开发者👨‍💻,我相信这篇文章都能给你带来一些新的见解🌟。

这样的格式更加吸引人,并且能在视觉上快速传达重要信息。希望这能帮助你!😊

1.1 什么是方法

Go 语言中同时有函数和方法。一个方法就是一个包含了接受者的函数,接受者可以是命名类型或者结构体类型的一个值或者是一个指针。所有给定类型的方法属于该类型的方法集

方法只是一个函数,它带有一个特殊的接收器类型,它是在func关键字和方法名之间编写的。接收器可以是struct类型或非struct类型。接收方可以在方法内部访问。

方法能给用户自定义的类型添加新的行为。它和函数的区别在于方法有一个接收者,给一个函数添加一个接收者,那么它就变成了方法。接收者可以是值接收者,也可以是指针接收者。

在调用方法的时候,值类型既可以调用值接收者的方法,也可以调用指针接收者的方法;指针类型既可以调用指针接收者的方法,也可以调用值接收者的方法。

也就是说,不管方法的接收者是什么类型,该类型的值和指针都可以调用,不必严格符合接收者的类型。

1.2 方法的语法

定义方法的语法

func (t Type) methodName(parameter list)(return list) {
  
}
func funcName(parameter list)(return list){
    
}

实例代码:

package main

import (  
    "fmt"
)

type Employee struct {  
    name     string
    salary   int
    currency string
}

/*
 displaySalary() method has Employee as the receiver type
*/
func (e Employee) displaySalary() {  
    fmt.Printf("Salary of %s is %s%d", e.name, e.currency, e.salary)
}

func main() {  
    emp1 := Employee {
        name:     "Sam Adolf",
        salary:   5000,
        currency: "$",
    }
    emp1.displaySalary() //Calling displaySalary() method of Employee type
}

可以定义相同的方法名

示例代码:

package main

import (
	"fmt"
	"math"
)

type Rectangle struct {
	width, height float64
}
type Circle struct {
	radius float64
}


func (r Rectangle) area() float64 {
	return r.width * r.height
}
//该 method 属于 Circle 类型对象中的方法
func (c Circle) area() float64 {
	return c.radius * c.radius * math.Pi
}
func main() {
	r1 := Rectangle{12, 2}
	r2 := Rectangle{9, 4}
	c1 := Circle{10}
	c2 := Circle{25}
	fmt.Println("Area of r1 is: ", r1.area())
	fmt.Println("Area of r2 is: ", r2.area())
	fmt.Println("Area of c1 is: ", c1.area())
	fmt.Println("Area of c2 is: ", c2.area())
}

运行结果

Area of r1 is:  24
Area of r2 is:  36
Area of c1 is:  314.1592653589793
Area of c2 is:  1963.4954084936207
  • 虽然method的名字一模一样,但是如果接收者不一样,那么method就不一样
  • method里面可以访问接收者的字段
  • 调用method通过.访问,就像struct里面访问字段一样

1.3 方法和函数

既然我们已经有了函数,为什么还要使用方法?

示例代码:

package main

import (  
    "fmt"
)

type Employee struct {  
    name     string
    salary   int
    currency string
}

/*
 displaySalary() method converted to function with Employee as parameter
*/
func displaySalary(e Employee) {  
    fmt.Printf("Salary of %s is %s%d", e.name, e.currency, e.salary)
}

func main() {  
    emp1 := Employee{
        name:     "Sam Adolf",
        salary:   5000,
        currency: "$",
    }
    displaySalary(emp1)
}

在上面的程序中,displaySalary方法被转换为一个函数,而Employee struct作为参数传递给它。这个程序也产生了相同的输出:Salary of Sam Adolf is $5000.。

为什么我们可以用函数来写相同的程序呢?有以下几个原因

  1. Go不是一种纯粹面向对象的编程语言,它不支持类。因此,类型的方法是一种实现类似于类的行为的方法。
  2. 相同名称的方法可以在不同的类型上定义,而具有相同名称的函数是不允许的。假设我们有一个正方形和圆形的结构。可以在正方形和圆形上定义一个名为Area的方法。这是在下面的程序中完成的。

1.4 变量作用域

作用域为已声明标识符所表示的常量、类型、变量、函数或包在源代码中的作用范围。

Go 语言中变量可以在三个地方声明:

  • 函数内定义的变量称为局部变量
  • 函数外定义的变量称为全局变量
  • 函数定义中的变量称为形式参数

局部变量

在函数体内声明的变量称之为局部变量,它们的作用域只在函数体内,参数和返回值变量也是局部变量。

全局变量

在函数体外声明的变量称之为全局变量,首字母大写全局变量可以在整个包甚至外部包(被导出后)使用。

package main

import "fmt"

/* 声明全局变量 */
var g int

func main() {

   /* 声明局部变量 */
   var a, b int

   /* 初始化参数 */
   a = 10
   b = 20
   g = a + b

   fmt.Printf("结果: a = %d, b = %d and g = %d\n", a, b, g)
}

结果

结果: a = 10, b = 20 and g = 30

形式参数

形式参数会作为函数的局部变量来使用

指针作为接收者

若不是以指针作为接收者,实际只是获取了一个copy,而不能真正改变接收者的中的数据

func (b *Box) SetColor(c Color) {
	b.color = c
}

示例代码

package main

import (
	"fmt"
)

type Rectangle struct {
	width, height int
}

func (r *Rectangle) setVal() {
	r.height = 20
}

func main() {
	p := Rectangle{1, 2}
	s := p
	p.setVal()
	fmt.Println(p.height, s.height)
}

结果

20 2

如果没有那个*,则值就是2 2

1.5 method继承

method是可以继承的,如果匿名字段实现了一个method,那么包含这个匿名字段的struct也能调用该method

package main

import "fmt"

type Human struct {
	name  string
	age   int
	phone string
}
type Student struct {
	Human  //匿名字段
	school string
}
type Employee struct {
	Human   //匿名字段
	company string
}

func (h *Human) SayHi() {
	fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone)
}
func main() {
	mark := Student{Human{"Mark", 25, "222-222-YYYY"}, "MIT"}
	sam := Employee{Human{"Sam", 45, "111-888-XXXX"}, "Golang Inc"}
	mark.SayHi()
	sam.SayHi()
}

运行结果:

Hi, I am Mark you can call me on 222-222-YYYY
Hi, I am Sam you can call me on 111-888-XXXX

1.6 method重写

package main

import "fmt"

type Human struct {
	name  string
	age   int
	phone string
}
type Student struct {
	Human  //匿名字段
	school string
}
type Employee struct {
	Human   //匿名字段
	company string
}

//Human定义method
func (h *Human) SayHi() {
	fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone)
}

//Employee的method重写Human的method
func (e *Employee) SayHi() {
	fmt.Printf("Hi, I am %s, I work at %s. Call me on %s\n", e.name,
		e.company, e.phone) //Yes you can split into 2 lines here.
}
func main() {
	mark := Student{Human{"Mark", 25, "222-222-YYYY"}, "MIT"}
	sam := Employee{Human{"Sam", 45, "111-888-XXXX"}, "Golang Inc"}
	mark.SayHi()
	sam.SayHi()
}

运行结果:

Hi, I am Mark you can call me on 222-222-YYYY
Hi, I am Sam, I work at Golang Inc. Call me on 111-888-XXXX
  • 方法是可以继承和重写的
  • 存在继承关系时,按照就近原则,进行调用

1.7 接口与方法

在 Go 语言中,接口定义了一组方法,但这些方法不包含实现代码。它们没有被绑定到特定的类型。接口的方法可以通过任何类型来实现,这样该类型就满足了接口。

type Sayer interface {
    Say() string
}

type Dog struct {
}

func (d Dog) Say() string {
    return "Woof!"
}

type Cat struct {
}

func (c Cat) Say() string {
    return "Meow!"
}

func AnimalTalk(s Sayer) {
    fmt.Println(s.Say())
}

func main() {
    var d Sayer = Dog{}
    var c Sayer = Cat{}

    AnimalTalk(d)
    AnimalTalk(c)
}

在这个例子里,Sayer 接口包含了一个 Say 方法。我们定义了两个结构体类型 DogCat,然后使它们都满足 Sayer 接口。最后,在 AnimalTalk 函数中使用接口作为参数,实现了多态。

1.8 方法的签名

每个方法都有一个方法签名,这告诉我们方法接受哪种类型的接收者。这非常重要,因为这决定了哪些方法属于接口类型,或者更通用地说,它决定了一组方法(以及它们的签名)如何形成一个接口。

type Geometry interface {
    Area() float64
    Perimeter() float64
}

type Square struct {
    side float64
}

func (s Square) Area() float64 {
    return s.side * s.side
}

func (s Square) Perimeter() float64 {
    return 4 * s.side
}

在这里,Geometry 接口包含 AreaPerimeter 方法,这两个方法都没有参数并返回一个浮点数。因此,任何具有这两个方法的类型都满足 Geometry 接口。

1.9 方法值和方法表达式

在 Go 中,方法不仅可以作为接收者类型的一部分来调用,还可以作为独立的值和表达式。

方法值

当你保存方法作为值时,接收者也会被保存。

type Greeter struct {
    Name string
}

func (g Greeter) Greet() {
    fmt.Println("Hello", g.Name)
}

func main() {
    greet := Greeter{Name: "John"}.Greet
    greet()
}

方法表达式

方法表达式返回一个函数,该函数接受一个接收者和原方法的其他参数。

type Adder struct {
    Base int
}

func (a Adder) Add(x int) int {
    return a.Base + x
}

func main() {
    add := Adder{Base: 2}.Add
    fmt.Println(add(3)) // Output: 5
}

1.10 方法的可见性

和字段或函数一样,如果方法的第一个字母是大写的,那么这个方法可以被这个包以外的代码访问。这是 Go 的导出规则。

package geometry

type Rectangle struct {
    Length, Width float64
}

func (r Rectangle) Area() float64 {
    return r.Length * r.Width
}

func (r Rectangle) perimeter() float64 {
    return 2 * (r.Length + r.Width)
}

在上面的例子中,Area 方法是导出的,因为它以大写字母开头,而 perimeter 则不是因为它以小写字母开头。

通过这些主题的讨论,希望能够增加你对 Go 语言中方法的深入理解。接下来,我们将探讨更高级的主题,以帮助你成为一名更出色的 Go 程序员。敬请期待!

总结🌟

掌握Go语言中的方法(Method)不仅是基础学习的重要一环,而且对于高级编程和实际应用也有着至关重要的作用。通过这篇文章,我希望你能对Go语言的方法有一个更全面和深入的理解,从而能够更加灵活和高效地使用这一强大的编程语言。

在这篇博客中,我详细讲解了Go语言中“方法”(Method)的重要性和应用。该博客是"100天精通Golang"系列的第19篇文章。主要内容围绕方法在Go语言中的基础语法、与函数的区别,以及方法的用法和应用范围进行了全面而深入的介绍。

1️⃣ 基础语法和定义方式: 方法是Go语言编程中的一个关键概念,理解它有助于写出更有序和可维护的代码。

2️⃣ 值接收者和指针接收者: 文章解释了这两种接收者的区别和各自适用的场合。

3️⃣ 方法与函数的对比: 了解这两者的不同能帮助你更准确地应用它们。

4️⃣ 局部变量和全局变量的应用: 在方法中,如何使用这两种变量也是一个需要注意的点。

5️⃣ 方法的继承与重写: 在面向对象编程中,了解如何继承和重写方法是非常重要的。

无论你是Go语言初学者还是经验丰富的开发者,这篇文章都提供了有价值的信息和见解。

通过这篇博客,你可以更全面地理解Go语言中的“方法”,从而更有效地使用Go进行编程。

参考资料

  1. “The Go Programming Language” by Alan A. A. Donovan & Brian W. Kernighan
  2. Go官方文档:Methods - The Go Programming Language
  3. “Go语言高级编程” by Chai2010
  4. Go by Example: Methods
  5. Understanding Go Interfaces

感谢大家的阅读,如果你觉得这篇文章有用,不妨分享给你的朋友和同事,也别忘了关注猫头虎博主的更多精彩内容!我们下篇文章见!

在这里插入图片描述

结语

通过今天的学习,您已经踏上了Golang的学习之旅。在未来的日子里,您将探索Golang的各个方面,从基础概念到高级技巧,从实际应用到性能优化。
学习一门编程语言是一个持续的过程,每一天都是您向Golang的精通迈进的重要一步。我鼓励您坚持每天学习,保持热情和好奇心,解决挑战并享受成功的喜悦。

在您的学习旅程中,不要忘记参与社区和与其他Golang开发者交流。分享您的见解和经验,向他人学习,并在开源项目或实际应用中展示您的技能。

如果您在学习过程中遇到困难或有任何问题,不要犹豫向社区和专家寻求帮助。持续学习,勇敢探索,您将在Golang领域取得令人瞩目的成就。

最后,感谢您的阅读和支持!祝愿您在未来的每一天中都能够成为一名精通Golang的开发者!

期待听到您在学习过程中的进展和成就。如果您需要进一步的帮助,请随时告诉我。祝您在学习Golang的旅程中取得巨大成功!

点击下方名片,加入IT技术核心学习团队。一起探索科技的未来,共同成长。

如果您在学习过程中有任何疑惑,请点击下方名片,带您一对一快速入门 Go语言 的世界 ~

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

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

相关文章

Python2022年09月Python二级 -- 编程题解析

第一题: 某航空公司对于托运行李有尺寸要求,必须满足以下条件:每件托运行李的长、宽、高三边之和须大于或等于60厘米,且小于或等于203厘米。(注意只是三边,不考虑立方体的整个周长,相当于只求长宽高三个数字的和,如&am…

Mysql的page,索引,Explain Type等基本常识

Mysql的基本问题 Mysql 为什么建议使用自增id? 因为id(主键)是自增的话,那么在有序的保存用户数据到页中的时候,可以天然的保存,并且是在聚集索引(id)中的叶子节点可以很好的减少插…

STM32H750+LAN8720无操作系统移植lwip

前言 本文提供移植好的工程&#xff0c;见本文绑定资源 环境 STM32CubeMX&#xff1a; V6.8.1 STM32H7 HAL Pack&#xff1a; V1.11.1 硬件连接 STM32H750 GPIO定义如下&#xff1a; LAN8720 GPIO定义如下&#xff1a; 连接方式如下&#xff1a; LAN8720       <—…

翻斗式雨量计入选【2023年济南市重点工业新产品】名单

近日&#xff0c;济南市工业和信息化局发布了【2023年济南市重点工业新产品】名单&#xff0c;山东仁科测控技术有限公司“翻斗式雨量计”成功入选。 为深入实施工业强市战略&#xff0c;切实加强创新示范推广与应用&#xff0c;鼓励企业研发新技术、新产品、新工艺&#xff0…

Android Native Code开发学习(三)对java中的对象变量进行操作

Android Native Code开发学习&#xff08;三&#xff09; 本教程为native code学习笔记&#xff0c;希望能够帮到有需要的人 我的电脑系统为ubuntu 22.04&#xff0c;当然windows也是可以的&#xff0c;区别不大 对java中的对象变量进行操作 首先我们新建一个java的类 pub…

全画面塑料激光透光率测试仪

随着光学塑料成型技术的不断发展&#xff0c;光学塑料透镜在各类光学系统中得到了广泛的应用。光学塑料具有便于大批量生产&#xff0c;设计灵活性高&#xff0c;重量轻和耐冲击等特点。最近几年来&#xff0c;国内外有许多专家学者对热塑性半结晶塑料激光焊接工艺上的应用进行…

Java入门第四节

Java入门第四节 一.继承 问题&#xff1a; 隔壁的王阿姨养了一只猫和一只仓鼠&#xff0c;也想使用这个app&#xff0c;应该这么办 解决&#xff1a; 1.找出所有动物的共性(如.有名字&#xff0c;品种&#xff0c;年龄&#xff0c;吃饭&#xff0c;跑等等)&#xff0c;创建…

IDEA工具栏快捷按钮

如图 点击快速弹出创建class. 主要我9.9的鼠标右键不灵敏 方法 在工具栏右键 横杠出点 Add Action 没有横杠就点下一个

QLabel控件使用

Qt为我们应用程序界面开发提供的一系列的控件&#xff0c;下面我们介绍两种最常用一些控件&#xff0c;所有控件的使用方法我们都可以通过帮助文档获取。 1.QLabel控件使用 QLabel是我们最常用的控件之一&#xff0c;其功能很强大&#xff0c;我们可以用来显示文本&#xff0c…

0830hw

1.2.链式队列 head.h #include <myhead.h> typedef int datatype; typedef struct seq {union{datatype data;int len;};struct seq *next; }seq,*S; typedef struct PP {S front;S rear; }P; P *create(); void input_tail(P *p,datatype n); void pop_head(P *p); vo…

Python程序化交易接口批量获取数据源码

小编举例下面是一个简单的示例代码&#xff0c;展示如何使用Python的程序化交易接口批量获取数据&#xff0c;例如开发文档参考&#xff1a;MetaTradeAPI (metatradeapi) - Gitee.com 签名 int Init(); 功能 API 初始化 参数 无 返回值 授权成功的交易账户数量 返回值 &…

使用STM32与TB6612FNG驱动直流减速电机

TB6612FNG介绍 单片机引脚的电流一般只有几十个毫安&#xff0c;无法驱动电机&#xff0c;因此一般是通过单片机控制电机驱动芯片进而控制电机。TB6612是比较常用的电机驱动芯片之一。 TB6612FNG可以同时控制两个电机&#xff0c;工作电流1.2A&#xff0c;最大电流3.2A。 AIN…

Java里面对int[]数组做新增删除去重实现

Java里面对int[]数组做新增删除去重实现 说明代码根据索引删除数组中的某个数据实现在数组中添加一个元素实现删除数组里面的重复数据去掉数组里面的重复数据&#xff0c;只保留一个 说明 这里记录下使用int[]数组对数组进行新增删除去重等操作&#xff0c;用来更加了解java里…

部署单点elasticsearch

部署elasticsearch 创建网络 因为我们还需要部署kibana容器&#xff0c;因此需要让es和kibana容器互联。这里先创建一个网络 docker network create es-net 拉取镜像 我们采用elasticsearch的7.12.1版本的镜像 docker pull elasticsearch:7.12.1 运行 运行docker命令&a…

编译KArchive在windows10下

使用QT6和VS2019编译KArchive的简要步骤&#xff1a; 安装 Qt &#xff0c;我是用源码自己编译的 "F:\qtbuild"安装CMakefile并配置环境变量安装Git下载ECM源码 https://github.com/KDE/extra-cmake-modules.git-------------------------------------------------…

springboot docker

在Spring Boot中使用Docker可以帮助你将应用程序与其依赖的容器化&#xff0c;并简化部署和管理过程。 当你在Spring Boot中使用Docker时&#xff0c;你的代码不需要特殊的更改。你可以按照通常的方式编写Spring Boot应用程序。 java示例代码&#xff0c;展示了如何编写一个基…

如何飞速成为开源贡献者(Contributor)

如何飞速成为开源贡献者Contributor 一、环境信息1.1 硬件信息1.2 软件信息 二、Git安装2.1 Git介绍2.2 Git下载安装 三、开源项目选定四、GitHub参与开源流程4.1 Fork项目4.2 SSH配置4.2.1 为什么要配置SSH4.2.2 如何配置SSH 4.3 Clone项目4.4 IDEA关联4.5 PR生成4.6 PR提交 一…

电脑突然提示msvcr120.dll错误的解决方法,最全面的解决方法

今天&#xff0c;我将和大家分享一种常见的电脑问题——电脑突然提示msvcr120.dll错误的解决方法。希望通过这次演讲&#xff0c;能够帮助大家解决这个问题&#xff0c;提高大家的电脑使用效率。首先&#xff0c;让我们来了解一下msvcr120.dll是什么。msvcr120.dll是Microsoft …

CMH检验

前言 CMH检验&#xff08;Cochran-Mantel-Haenszel Test&#xff09;&#xff0c;分层卡方检验&#xff0c;考虑中心效应&#xff0c;分析干预对结果的影响。如果存在中心效应&#xff0c;即干预结果与中心相关&#xff0c;那么简单的将中心数据合并做卡方分析并不合理。需要采…

记事本编辑代码出错?编程初学者为什么不要用系统文本编辑器? 文本编辑器踩坑指南,代码格式化无效,写代码必看

题目: 写一段判断 2 到 10 之间的质数的输出 环境 左: VScode 右: Windows 文本编辑器(记事本) 目录 代码展示 原视频介绍 图文介绍 更离谱的是使用vscode 一键格式化 摆烂??? 最终手动缩进才解决问题 解决问题 那么问题究竟出在哪里? 文本比较即可 还是不够直…