您的位置:首页 > 财经 > 金融 > 网页升级访问正在跳转中_上海seo网站建设_外贸网站seo_sem和seo区别与联系

网页升级访问正在跳转中_上海seo网站建设_外贸网站seo_sem和seo区别与联系

2024/12/23 8:51:34 来源:https://blog.csdn.net/llllinuuu/article/details/143601283  浏览:    关键词:网页升级访问正在跳转中_上海seo网站建设_外贸网站seo_sem和seo区别与联系
网页升级访问正在跳转中_上海seo网站建设_外贸网站seo_sem和seo区别与联系

文章目录

  • 一、结构体构造函数
      • Go语言中的构造函数语法
  • 二、结构体方法和接收器
      • 无参数和返回值
      • 值类型接收者
      • 指针类型接收者
        • 方法继承
        • 方法重写
  • 三、结构体比较
      • 结构体比较要求
      • 结构体比较符号
  • 四、接口声明
      • 接口定义
      • 接口特点
      • 接口格式
      • 标准格式接口的实现:
      • 空接口
      • error接口
  • 五、接口与结构体
      • 接口与结构体的关系
      • 一个结构体类型实现多个接口
      • 一个接口被多个结构体实现
  • 六、接口的嵌套
      • 接口嵌套的定义
      • 接口嵌套的格式

一、结构体构造函数

Go语言中的构造函数:

  • Go 语言没有构造函数的功能
  • 使用结构体初始化的过程来模拟实现构造函数
  • 结构体可以像其他数据类型一样将结构体类型作为参数传递给函数

在这里插入图片描述

Go语言中的构造函数语法

type 类型名 struct {字段名1 字段类型1字段名2 字段类型2......
}
func newfunc(变量名1 变量类型, 变量名2 变量类型 ……) *类型名{return &类型名{字段名1: 变量1,字段名2: 变量2......}
}
  • Go语言的类型或结构体没有构造函数的功能,但是我们可以使用结构体初始化的过程来模拟实现构造函数。
  • 构造函数传入的变量类型需要与return返回结构体指针字段名类型一致
  • 构造函数可以只返回结构体中某些字段名

示例1:

package main
import "fmt"
type person struct {name stringage  int
}
//构造函数约定俗成用new开头,不是强制
//返回的是结构体还是结构体指针
//当结构体比较大的时候使用结构体指针,减少程序内存的开销。
func personOnlyName(name string) *person {return &person{name: name,}//仅返回部分字段
}func newperson(name string, age int) *person {return &person{name: name,age:  age,}//返回所有字段
}
func main()  {p1 := personOnlyName("Go语言")fmt.Println(p1)p2 := newperson("golang", 20)fmt.Println(p2)
}//运行结果:
//&{Go语言 0}
//&{golang 20}

示例2:

package main
import "fmt"
type person struct {name stringage  int
}
func print1(p person){p.name="值传递"fmt.Println("print1",p)
}
func print2(p *person){p.name="指针传递"fmt.Println("print2",p)
}func main()  {p1:=person{"Go语言",20}print1(p1)	      //值传递,形参无法改实参fmt.Println(p1)print2(&p1)  //指针传递,形参可以改实参fmt.Println(p1)
}//运行结果:
//print1 {值传递 20}
//{Go语言 20}
//print2 &{指针传递 20}
//{指针传递 20}

二、结构体方法和接收器

Go语言同时有函数和方法,方法的本质是函数,但是方法和函数又具有不同点。
在这里插入图片描述在这里插入图片描述

无参数和返回值

func (结构体变量 结构体类型) 方法名() {函数体
}

值类型接收者

func (接收者变量 接收者类型) 方法名(参数列表) (返回参数) {函数体
}

指针类型接收者

func (接收者变量 *接收者类型) 方法名(参数列表) (返回参数) {函数体
}

示例:

package main
import "fmt"
type person struct {name stringage  int
}
func (p person)print(){  //无参数和返回值fmt.Println(p)
}
func (p person)change1(s string){p.name=s  //值类型接收者
}
func (p *person)change2(s string){p.name=s   //指针类型接收者
}func main()  {p := person{"Go",20}p.print()p.change1("Golang")p.print()p.change2("Go语言")p.print()
}//运行结果为:
//{Go 20}
//{Go 20}
//{Go语言 20}

若方法的接受者不是指针,实际只是获取了一个copy,而不能真正改变接受者中原来的数据。

使用方法的原因:

  • 既然可以用函数来写相同的程序,却还要使用方法,主要有以下两个原因
  • 如Go不是一种纯粹面向对象的编程语言,它不支持类。因此其方法是一种实现类似于类的行为的方法。
  • 如果相同名称的方法可以在不同的类型上定义,而具有相同名称的函数是不允许的。假设有一个正方形和圆形的结构。可以在正方形和圆形上定义一个名为Area的求取面积的方法。
  • 下面通过一个示例来观察不同的结构体中方法名。

示例:

package main
import ("math""fmt"
)
type Rectangle struct {width, height float64
}
type Circle struct {radius float64
}
func main() {r1 := Rectangle{10, 4}r2 := Rectangle{12, 5}c1 := Circle{1}c2 := Circle{10}    fmt.Println("r1 的面积", r1.Area())fmt.Println("r2 的面积", r2.Area())fmt.Println("c1 的面积", c1.Area())fmt.Println("c2 的面积", c2.Area())
}
func (r Rectangle) Area() float64 {return r.width * r.height
}   // 定义 Rectangle 的方法
func (c Circle) Area() float64 {return c.radius * c.radius * math.Pi
}   // 定义 Circle 的方法//运行结果为:r1 的面积 40
//r2 的面积 60
//c1 的面积 3.141592653589793
//c2 的面积 314.1592653589793
方法继承
  • 方法是可以继承的,如果匿名字段实现了一个方法,那么包含这个匿名字段的struct也能调用该匿名结构体中的方法。
方法重写
  • 方法是可以继承和重写的。

示例:

package main
import "fmt"
type Human struct { name  stringphone stringage   int
}
type Student struct { // 继承HumanHuman  // 嵌入Human,匿名字段school string
} 
type Employee struct {Human   // 匿名字段company string
}  // Human的SayHi方法
func (h Human) SayHi() {fmt.Printf("大家好! 我是%s,%d岁,联系方式是: %s\n", h.name, h.age, h.phone)
}  
func main() {s1 := Student{Human
{"Daniel", "15012345678", 13}, "十一中学"}e1 := Employee{Human
{"Steven", "17812345678", 35}, "1000phone"}s1.SayHi()e1.SayHi()
}
package main
import "fmt"
type Human struct {name  stringphone stringage   int
}
type Student struct {Human  //继承Humanschool string
}
type Employee struct {Human  //继承Humancompany string
}
func (h Human) SayHi() {
fmt.Printf("大家好! 我是%s,%d岁,联系方式是: %s\n", h.name, h.age, h.phone)
}
func (s Student) SayHi() {
fmt.Printf("大家好! 我是%s,%d岁,我在%s上学,联系方式是: %s\n", s.name, s.age, s.school, s.phone)
}
func (e Employee) SayHi() {
fmt.Printf("大家好! 我是%s,%d岁,我在%s工作,联系方式是: %s\n", e.name, e.age, e.company, e.phone)  }
func main() {s1 := Student{Human{"Daniel", "15012345678", 13}, "十一中学"}e1 := Employee{Human{"Steven", "17812345678", 35}, "1000phone"}s1.SayHi() // 调用各自的SayHi方法e1.SayHi()
}

三、结构体比较

结构体比较要求

  • 结构体可以比较,也不可以比较
  • 如果结构体的全部成员都是可以比较的,那么结构体也是可以比较的
  • 如果包含slice、map、function不可比较类型时,那么结构体是不可以比较的

结构体比较符号

  • 可以比较的情况下:两个结构体将可以使用**==或!=运算符进行比较,但不支持>或<**
  • 同类型的两个结构体变量可以相互赋值

示例1:

package main
import "fmt"
type person struct {name stringage  int
}
func main()  {p1 :=person{"Go语言",20}p2 :=person{"Go语言",20}if p1==p2{fmt.Println("p1=p2")}else {fmt.Println("p1!=p2")}
}//运行结果为:
//p1=p2

示例2:

package main
import "fmt"
type person struct {name stringage  []int
}
func main()  {p1 :=person{"Go语言",[]int{20}}p2 :=person{"Go语言",[]int{20}}if p1==p2{fmt.Println("p1=p2")}else {fmt.Println("p1!=p2")}
}//报错提示:
//invalid operation: p1 == p2 (struct containing []int cannot be compared)

!! 不能比较包含[]int的结构体

示例3:

package main
import "fmt"
type person1 struct {name stringage  int
}
type person2 struct {name stringage  int
}
func main()  {p1 :=person1{"Go语言",20}p2 :=person2{"Go语言",20}if p1==p2{fmt.Println("p1=p2")}else {fmt.Println("p1!=p2")}
}//报错提示:
//invalid operation: p1 == p2 (mismatched types person1 and person2)

!! 结构体不同则不能比较

示例4:

package main
import "fmt"
type person1 struct {name stringage  int
}
type person2 struct {name stringage  int
}
func main()  {p1 :=person1{"Go语言",20}p2 :=person2{"Go语言",20}if p1==person1(p2){fmt.Println("p1=p2")}else {fmt.Println("p1!=p2")}
}//运行结果:
//p1=p2

结构体内部相同时,可以使用强制转换来实现比较

四、接口声明

接口

  • 面向对象语言中,接口用于定义对象的行为。接口只指定对象应该做什么,实现这种行为的方法(实现细节)是由对象来决定。
  • 接口定义了一组方法,如果某个对象实现了该接口的所有方法,则此对象就实现了该接口。

Go语言是一种“鸭子类型”的语言

  • Go没有 implements, extends 关键字,其实这种编程语言叫做duck typing编程语言。
  • duck typing是描述事物的外部行为而非内部结构。在“鸭子类型”中,关注的不是对象的类型本身,而是它是如何使用的。

接口定义

  • 接口是对类型行为的约定
  • 接口是一系列方法的集合
  • 接口是一种高度抽象的数据类型
  • 接口中的方法不包含代码
  • 接口中的方法是抽象的
  • 接口中不包含变量
  • 本质是一种关于对象功能的约定

接口特点

  • 接口是双方约定的一种合作协议,接口实现者不需要关心接口会怎样被使用,只需要实现接口里面所有的方法即可
  • 接口不支持直接实例化,只能通过具体的类来实现声明的所有方法,同时函数的函数名、函数参数和函数返回值必须完全一样
  • Go语言中的接口支持赋值操作,从而快速实现接口与实现类的映射

接口格式

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

接口要点:

  • 接口类型名:使用 type 将接口定义为自定义的类型名,接口在命名时,一般会在单词后面添加er;
  • 方法名:当方法名首字母是大写时,同时接口类型名首字母也是大写时,这个方法可以被接口所在的包(package)之外的代码访问;
  • 参数列表:表示传入到方法中的值;
  • 返回值列表:方法返回值。
    示例:
type Phone interface {call()SendMsg(msg string) bool
}

标准格式接口的实现:

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

示例:

//标准格式接口的实现案列
type AndroidPhone struct {
}  //实现接口的结构体func (a AndroidPhone) call() {fmt.Println("AndroidPhone calling")
}func (a AndroidPhone) SendMsg(msg string) bool {fmt.Println("AndroidPhone sending msg")return true
}

空接口

  • 是接口类型的特殊形式
  • 空接口没有任何方法,因此任何类型都无须实现空接口
  • 从实现的角度看,任何值都满足这个接口的需求
  • 空接口类型可以保存任何值,也可以从空接口中取出原值

示例:

package main
import "fmt"
func main() {var any interface{}any = 1fmt.Println(any)any = "hello"fmt.Println(any)any = falsefmt.Println(any)
}//运行结果为:
//1
//hello
//false

error接口

  • 作为错误处理的标准模式
  • 如果函数要返回错误,则返回值类型列表中肯定包含 error
  • error 处理过程类似于C语言中的错误码,可逐层返回,直到被处理

示例:

package main
import ("errors""fmt""math"
)
func Sqrt(f float64) (float64, error) {if f < 0 {return -1, errors.New("开平方根的数字不能小于0")}return math.Sqrt(f), nil
}
func main() {result, err := Sqrt(-13)if err != nil {fmt.Println(err)} else {fmt.Println(result)}
}//运行结果为:
//开平方根的数字不能小于0

五、接口与结构体

接口与结构体的关系

在这里插入图片描述

一个结构体类型实现多个接口

格式:

type 接口类型名1 interface{方法名1( 参数列表1 ) 返回值列表1
}
type 接口类型名2 interface{方法名2( 参数列表2 ) 返回值列表2
}type 结构体 struct{字段名1  字段类型1字段名2  字段类型2
}
type (结构体名 结构体) 方法名1( 参数列表1 ) 返回值列表1{
}
type (结构体名 结构体) 方法名2( 参数列表2 ) 返回值列表2{
}

示例:

package main
import "fmt"
type run interface{running(time int)int
}
type eat interface{eating(food string)int
}
type person struct {weight int
}
func (p *person)running(time int)int{p.weight -= time/5return p.weight
}
func (p *person)eating(food string)int{p.weight += 1return p.weight
}
func main() {p1 :=&person{weight: 50,}fmt.Println(p1.weight)p1.running(20)fmt.Println(p1.weight)p1.eating("面包")fmt.Println(p1.weight)//运行结果为:
//50
//46
//47

一个接口被多个结构体实现

格式:

type 接口类型名 interface{方法名1( 参数列表1 ) 返回值列表1方法名2( 参数列表2 ) 返回值列表2
}
type 结构体1 struct{字段名1  字段类型1
}
type 结构体2 struct{字段名2  字段类型2
}
type 结构体3 struct{字段名3 字段类型3
}
type (结构体名1 结构体1) 方法名1( 参数列表1 ) 返回值列表1{
}
type (结构体名2 结构体2) 方法名2( 参数列表2 ) 返回值列表2{
}
type (结构体名3 结构体3) 方法名2( 参数列表2 ) 返回值列表2{
}

示例:

package main
import "fmt"
type who interface{who(position string)string
}
type tearcher struct {position stringname string
}
type student struct {position stringname string
}
func (t *tearcher)who(name string)string{t.position="教师"t.name=namereturn t.position
}
func (s *student)who(name string)string{s.position="学生"s.name=namereturn s.position
}
func main() {var t who=&tearcher{position: "未知",name: "未知",}t.who("Go")fmt.Println(t)var s who=&student{position: "未知",name: "未知",}s.who("go")fmt.Println(s)
}//运行结果为:
//&{教师 Go}
//&{学生 go}

六、接口的嵌套

接口嵌套的定义

在Go 语言中,不仅仅结构体与结构体之间可以嵌套,接口与接口之间也可以嵌套,被包含的接口中的所有方法都会被包含到新的接口中。

接口嵌套的格式

type 接口类型名1 interface{方法名1()
}
type 接口类型名2 interface{方法名2()
}
type 接口类型名3 interface{接口类型名1接口类型名2方法名3()
}

一个接口可以包含一个或多个其他的接口,这相当于直接将这些内嵌接口的方法列举在外层接口中一样。只要接口的所有方法被实现,则这个接口中的所有嵌套接口的方法均可以被调用。

//接口未嵌套
type queue interface {height()
}
type run interface {weight()
}
type BMI interface {height()weight()age()
}
//接口嵌套
type queue interface {height()
}
type run interface {weight()
}
type BMI interface {queuerunage()
}

示例:嵌套接口的实现

package main
import "fmt"
type queue interface {height() int
}
type run interface {weight() int
}
type BMI interface {queue //嵌套接口runage() int
}
type Person struct {  //结构体h, w, a int
}
func (p Person) height() int {return p.h 
}     // 实现queue接口的height方法
func (p Person) weight() int {return p.w
}   
func (p Person) age() int {return p.a
} 
func main() {p := Person{h: 170, w: 65, a: 25}fmt.Println("Height:", p.height())fmt.Println("Weight:", p.weight())fmt.Println("Age:", p.age())
}//运行结果为:
//Height: 170
//Weight: 65
//Age: 25

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com