国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

go 結(jié)構(gòu)體 - 值類型、引用類型 - 結(jié)構(gòu)體轉(zhuǎn)json類型 - 指針類型的種類 - 結(jié)構(gòu)體方法 - 繼承 - 多態(tài)(interface接口) - 練習(xí)

這篇具有很好參考價(jià)值的文章主要介紹了go 結(jié)構(gòu)體 - 值類型、引用類型 - 結(jié)構(gòu)體轉(zhuǎn)json類型 - 指針類型的種類 - 結(jié)構(gòu)體方法 - 繼承 - 多態(tài)(interface接口) - 練習(xí)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

目錄

一、結(jié)構(gòu)體

1、python 與?go面向?qū)ο蟮膶?shí)現(xiàn):

2、初用GO中的結(jié)構(gòu)體:(實(shí)例化一個(gè)值類型的數(shù)據(jù)(結(jié)構(gòu)體))

輸出結(jié)果不同的三種方式?

3、實(shí)例化一個(gè)引用類型的數(shù)據(jù)(結(jié)構(gòu)體)

4、引用類型(指針類型) vs 值類型(兩者的區(qū)別)

引用類型(指針類型) - 值類型內(nèi)存拓?fù)鋱D:

5、結(jié)構(gòu)體匿名字段、匿名結(jié)構(gòu)體

6、結(jié)構(gòu)體的嵌套

7、結(jié)構(gòu)體轉(zhuǎn)json類型

二、指針類型的種類(結(jié)構(gòu)體指針、數(shù)據(jù)變量指針、指針數(shù)組、數(shù)組指針)

三、結(jié)構(gòu)體方法(普通方法、指針方法)

四、結(jié)構(gòu)體繼承:

五、結(jié)構(gòu)體多態(tài):(interface接口的運(yùn)用)

1、空接口的定義:

2、接口如何實(shí)現(xiàn)自定義error呢?

1、練習(xí):判斷Role(角色)是否存活

2、練習(xí):實(shí)現(xiàn)發(fā)郵件功能

3、練習(xí):定義標(biāo)準(zhǔn)化返回(json格式)


一、結(jié)構(gòu)體

結(jié)構(gòu)體(Struct)是一種在Go語言中用于定義復(fù)合數(shù)據(jù)類型的機(jī)制。它允許你將不同類型的數(shù)據(jù)組合在一起,形成一個(gè)自定義的數(shù)據(jù)類型,以便更方便地管理和操作相關(guān)數(shù)據(jù)。

在Go語言中,通過type關(guān)鍵字和字段列表來定義結(jié)構(gòu)體。每個(gè)字段都可以有自己的數(shù)據(jù)類型,類似于其他編程語言中的類的成員變量。結(jié)構(gòu)體中的字段可以包含任意類型的數(shù)據(jù),包括基本數(shù)據(jù)類型(如整數(shù)、浮點(diǎn)數(shù)、字符串等)和其他自定義類型(如其他結(jié)構(gòu)體、數(shù)組、切片等)。

結(jié)構(gòu)體中可以定義多個(gè)字段,類似于python中class類的屬性

以下是一個(gè)簡(jiǎn)單的例子來說明如何定義和使用結(jié)構(gòu)體:

package main

import "fmt"

// 定義一個(gè)Person結(jié)構(gòu)體
type Person struct {
    Name string
    Age  int
}

func main() {
    // 創(chuàng)建一個(gè)Person類型的變量
    var person1 Person

    // 設(shè)置person1的字段值
    person1.Name = "Alice"
    person1.Age = 30

    // 打印person1的字段值
    fmt.Println(person1) // 輸出:{Alice 30}

    // 創(chuàng)建并初始化Person結(jié)構(gòu)體的另一個(gè)變量
    person2 := Person{
        Name: "Bob",
        Age:  25,
    }

    // 打印person2的字段值
    fmt.Println(person2) // 輸出:{Bob 25}
}

在上述示例中,我們通過type關(guān)鍵字定義了一個(gè)名為Person的結(jié)構(gòu)體。該結(jié)構(gòu)體有兩個(gè)字段,分別為NameAge,分別用來存儲(chǔ)人的姓名和年齡。

main函數(shù)中,我們創(chuàng)建了兩個(gè)Person類型的變量person1person2,并分別設(shè)置了它們的字段值??梢酝ㄟ^運(yùn)算符來訪問結(jié)構(gòu)體變量的字段。

1、python 與?go面向?qū)ο蟮膶?shí)現(xiàn):

python 支持面向?qū)ο蟮? --》?class 類

go? ? ? ? 不支持面向?qū)ο缶幊?,可以使?strong>結(jié)構(gòu)體來實(shí)現(xiàn)類似的功能

  python => 面向?qū)ο?  class Student(object):
      def __init__(self, id, name, age):
           self.id = id
           ....

  go => 支持結(jié)構(gòu)體
type struct_name struct{
	field_name1 field_type
	field_name2 field_type
	field_name3 field_type
	...
}

2、初用GO中的結(jié)構(gòu)體:(實(shí)例化一個(gè)值類型的數(shù)據(jù)(結(jié)構(gòu)體))

// 定義一個(gè)Student結(jié)構(gòu)體
type Student struct {
	id int
	name string
	age uint
	school string
}

func main(){
    // 實(shí)例化一:實(shí)例化一個(gè)值類型的數(shù)據(jù)(結(jié)構(gòu)體)
	// 實(shí)例化的時(shí)候,可以只初始化部分?jǐn)?shù)據(jù)
	zrp := Student{
		id:     1,
		name:   "zrp",
	}
    //輸出結(jié)果不同的三種方式
	fmt.Printf("%v\n", zrp)
	fmt.Printf("%+v\n", zrp)
	fmt.Printf("%#v\n", zrp)

    // 初始化的時(shí)候,如果不指定字段名,就需要每個(gè)字段都賦值
    // 否則會(huì)報(bào)錯(cuò):too few values in Student{…}
    wbw :=Student{2,"wbw",20, "nongda"}
    // 值類型的數(shù)據(jù)要看地址的話,需要加&
	fmt.Printf("%#v,地址:%p\n", wbw, &wbw)

}

輸出:
{1 zrp 0 }
{id:1 name:zrp age:0 school:}
main.Student{id:1, name:"zrp", age:0x0, school:""}
main.Student{id:2, name:"wbw", age:0x14, school:"nongda"},地址:0xc000100540

輸出結(jié)果不同的三種方式?

fmt.Printf("%v\n", zrp)
fmt.Printf("%+v\n", zrp)
fmt.Printf("%#v\n", zrp)

輸出:

{1 zrp 0 }
{id:1 name:zrp age:0 school:}
main.Student{id:1, name:"zrp", age:0x0, school:""}

3、實(shí)例化一個(gè)引用類型的數(shù)據(jù)(結(jié)構(gòu)體)(指針類型)

定義的兩種方式:

1、mq := new(Student) (創(chuàng)建之后,只分配了內(nèi)存,因此不能直接定義數(shù)據(jù))

2、mq := &Student{ .... } (可以直接賦予初始值)

package main

import "fmt"

// 定義一個(gè)Student結(jié)構(gòu)體
type Student struct {
	id int
	name string
	age uint
	school string
}

func main(){

	// 實(shí)例化一個(gè)引用類型
	// 使用new實(shí)例化開辟一片內(nèi)存空間,創(chuàng)建一個(gè)實(shí)例對(duì)象,返回這個(gè)對(duì)象的內(nèi)存地址
	mq := new(Student)   //使用new實(shí)例化只開辟一片內(nèi)存空間 , mq是引用類型的數(shù)據(jù),不能直接賦值
	mq.id = 3            //
	mq.name = "mq"
	mq.age = 18
	fmt.Printf("%#v,地址:%p\n", mq, mq)
}

輸出:
&main.Student{id:3, name:"mq", age:0x12, school:""},0xc00000a028

4、引用類型(指針類型) vs 值類型(兩者的區(qū)別)(結(jié)構(gòu)體的實(shí)例化)

package main

import "fmt"

// 定義一個(gè)Student結(jié)構(gòu)體
type Student struct {
	id int
	name string
	age uint
	school string
}

func main(){
    // 實(shí)例化一個(gè)值類型的數(shù)據(jù)(如果沒有指定字段名,則需要給所有結(jié)構(gòu)體內(nèi)定義的變量賦值)
    wbw := Student{2,"wbw",20, "nongda"}
    // (如果指定了字段名,只需要給對(duì)應(yīng)的字段名賦值即可)
    // wbw := Student{id:2, name:"wbw"}

    // 實(shí)例化一個(gè)引用類型的數(shù)據(jù)
	mq := new(Student)
	mq.id = 3
	mq.name = "mq"
	mq.age = 18

    // 引用類型(指針類型) vs 值類型 區(qū)別

	// 引用類型 => 指向了一個(gè)內(nèi)存數(shù)據(jù),注意:如果要修改的話,一同變化
	mq2 := mq
	mq2.name = "米強(qiáng)"
	fmt.Printf("type:%T,values:%+v,address:%p\n",mq, mq,mq)
	fmt.Printf("type:%T,values:%+v,address:%p\n",mq2, mq2,mq2)
	// 值類型:兩份數(shù)據(jù),相互不影響
	wbw2 := wbw
	wbw2.name = "王百文"
	fmt.Printf("type:%T,values:%+v,address:%p\n",wbw, wbw, &wbw)
	fmt.Printf("type:%T,values:%+v,address:%p\n",wbw2, wbw2,&wbw2)
}

輸出:
type:*main.Student,values:&{id:3 name:米強(qiáng) age:18 school:},address:0xc0001004e0
type:*main.Student,values:&{id:3 name:米強(qiáng) age:18 school:},address:0xc0001004e0
type:main.Student,values:{id:2 name:wbw age:20 school:nongda},address:0xc0001004b0
type:main.Student,values:{id:2 name:王百文 age:20 school:nongda},address:0xc000100570

引用類型(指針類型) - 值類型內(nèi)存拓?fù)鋱D:

go 結(jié)構(gòu)體 - 值類型、引用類型 - 結(jié)構(gòu)體轉(zhuǎn)json類型 - 指針類型的種類 - 結(jié)構(gòu)體方法 - 繼承 - 多態(tài)(interface接口) - 練習(xí),golang,開發(fā)語言,后端

5、結(jié)構(gòu)體匿名字段、匿名結(jié)構(gòu)體

package main

import "fmt"

// 結(jié)構(gòu)體匿名字段 => 如果沒有定義字段名,會(huì)用類型的名字直接充當(dāng)字段名
type Stu struct {
	string
	int
}

func main(){
	// 結(jié)構(gòu)體匿名字段實(shí)例化
	st1 := Stu{"abc", 100}
	fmt.Printf("st1:%+v\n", st1)

    // 匿名結(jié)構(gòu)體: 適合一次性使用
	stu2 := struct {
		name string
		age int
	}{"cali", 30}
	fmt.Printf("st2:%+v\n", stu2)
}

輸出:
st1:{string:abc int:100}
st2:{name:cali age:30}

6、結(jié)構(gòu)體的嵌套

package main

import "fmt"

// 結(jié)構(gòu)體的嵌套
type Book struct {
	title string
	Author struct{
		name, tel string
		age int
	}
}

func main(){

	// 嵌套結(jié)構(gòu)體的實(shí)例化
	b1 := Book{title: "GO從入門到精通"}
	b1.Author.name = "cici"
	b1.Author.tel = "186xxxxxxxx"
	fmt.Printf("b1:%+v\n", b1)
}

輸出:
b1:{title:GO從入門到精通 Author:{name:cici tel:186xxxxxxxx age:0}}

7、結(jié)構(gòu)體轉(zhuǎn)json類型

結(jié)構(gòu)體可以直接轉(zhuǎn)換為json格式

go 結(jié)構(gòu)體 - 值類型、引用類型 - 結(jié)構(gòu)體轉(zhuǎn)json類型 - 指針類型的種類 - 結(jié)構(gòu)體方法 - 繼承 - 多態(tài)(interface接口) - 練習(xí),golang,開發(fā)語言,后端

json.Marshal( 結(jié)構(gòu)體實(shí)例 )

json字符串一般key都是由小寫組成

package main

import (
	"encoding/json"
	"fmt"
)

// Web開發(fā),數(shù)據(jù)定義都是結(jié)構(gòu)體類型 結(jié)構(gòu)體數(shù)據(jù) <=> json <=>前端
// 加Tag(兩個(gè)反引號(hào)``): Tag加上json配置項(xiàng):他當(dāng)將結(jié)構(gòu)體轉(zhuǎn)換成json的時(shí)候讀取該配置
// Student結(jié)構(gòu)體內(nèi)的數(shù)據(jù)轉(zhuǎn)換為json格式
type Student struct{
    // 轉(zhuǎn)換json格式
	Id int			`json:"id"`
	Name string		`json:"username"`

	// 設(shè)置成“-” => 表示忽略該字段
	School string	`json:"-"`

	// 如果沒有配置 => 使用默認(rèn)字段名
	School2 string  // 大寫開頭表示公開
    school2 string  // 小寫開頭表示私有

	// omitempty如果當(dāng)前字段School3有值的,會(huì)顯示出來,如果沒有值就不會(huì)顯示
	School3 string 	`json:"school,omitempty"`
}

// 使用json模塊
// go結(jié)構(gòu)體數(shù)據(jù) <=> json <=>前端
func main(){
    // 實(shí)例化
	s1 := Student{
		Id:     1,
		Name:   "user1",
		School: "nongda",
		School3: "nongda3",  // omitempty會(huì)導(dǎo)致如果School3沒有值就不會(huì)顯示School3字段
	}
    // 用于進(jìn)行g(shù)o的異常處理
	bmarshal, err := json.Marshal(s1)
	if err == nil {
        // 輸出轉(zhuǎn)換后的json格式數(shù)據(jù)
		fmt.Println(string(bmarshal))
	}else{
        // 輸出其中的錯(cuò)誤
		fmt.Println("err:", err)
	}
}

輸出:
{"id":1,"username":"user1","School2":"","school":"nongda2"}

二、指針類型的種類(結(jié)構(gòu)體指針、數(shù)據(jù)變量指針、指針數(shù)組、數(shù)組指針)

package main

import "fmt"

// 定義一個(gè)Student結(jié)構(gòu)體
type Student struct {
	id int
	name string
	age uint
	school string
}

func main(){
	// 結(jié)構(gòu)體指針
	mc := &Student{
		id: 4,
		name: "mc",
	}
	fmt.Printf("type:%T, values:%+v\n", mc, mc)

	// 結(jié)構(gòu)體指針中,可以使用簡(jiǎn)化的語法
	fmt.Printf("%+v, %s\n", mc, (*mc).name)
	fmt.Printf("%+v, %s\n", mc, mc.name)

	// 數(shù)據(jù)變量指針獲取數(shù)據(jù)的方法
	var n1 *int  // 定義n1為int指針
	n2 := 10     // 給n2賦值
	n1 = &n2     // 將n2的地址傳給n1指針
	*n1 = 20     // 給n1指針賦值為20
	fmt.Printf("type:%T,address:%p, value:%d\n",n1, n1, *n1)
	fmt.Printf("address:%p, value:%d\n",&n2, n2)

    // 指針數(shù)組 parr是一個(gè)數(shù)組,有4個(gè)元素,每個(gè)元素都是一個(gè)int類型的指針
    var parr [4]*int
	a := 10
	parr[2] = &a
	fmt.Printf("value:%v, address:%v\n", *parr[2], parr[2])

    // 數(shù)組指針:是一個(gè)指針,指向了一個(gè)數(shù)組類型的數(shù)據(jù)(訪問數(shù)據(jù)的時(shí)候,可以使用簡(jiǎn)化方式)
    var parr2 *[4]int
	arr := [4]int{1,2,3,4}
	parr2 = &arr
	fmt.Printf("arrvalue:%v, value:%v, value:%v\n", parr2, (*parr2)[0], parr2[0])
}

輸出:
type:*main.Student, values:&{id:4 name:mc age:0 school:}
type:*int,address:0xc0000a60a0, value:20
address:0xc0000a60a0, value:20
&{id:4 name:mc age:0 school:}, mc
&{id:4 name:mc age:0 school:}, mc
value:10, address:0xc00000e138
arrvalue:&[1 2 3 4], value:1, value:1

三、結(jié)構(gòu)體方法(普通方法、指針方法)

結(jié)構(gòu)體的定義方式:

func (結(jié)構(gòu)體形參 結(jié)構(gòu)體類型)? 函數(shù)名(函數(shù)參數(shù)) 函數(shù)返回值 { .... }

兩種定義方式:值類型結(jié)構(gòu)體、指針類型結(jié)構(gòu)體

值類型結(jié)構(gòu)體:在函數(shù)內(nèi)部修改數(shù)據(jù)并不會(huì)影響函數(shù)外面

指針類型結(jié)構(gòu)體:在函數(shù)中修改了數(shù)據(jù)會(huì)影響外部的數(shù)據(jù)

package main

import "fmt"
// 結(jié)構(gòu)體方法的實(shí)現(xiàn)
// 在普通函數(shù)前加上一個(gè)接收者(receiver)
// func (s receiverType) funcName(args...)  --》 結(jié)構(gòu)體方法的定義

// 定義一個(gè)Student結(jié)構(gòu)體
type Student struct {
	id int
	name string
	age uint
	school string
}

// 為Student結(jié)構(gòu)綁定一個(gè)changeSchool方法 (值類型的結(jié)構(gòu)體,在函數(shù)內(nèi)部修改數(shù)據(jù)并不會(huì)影響函數(shù)外面)
func (s Student) changeSchool(school string){
	s.school = school
}

// 為*Student(指針)結(jié)構(gòu)體綁定一個(gè)changeSchool2方法 (指針類型的結(jié)構(gòu)體,在函數(shù)中修改了數(shù)據(jù)會(huì)影響外部的數(shù)據(jù))
func (s *Student) changeSchool2(school string){
	s.school = school
}

// 因此我們?cè)谡{(diào)用結(jié)構(gòu)體方法的時(shí)候,需要注意是什么結(jié)構(gòu)體類型
func main(){
	// 實(shí)例化一個(gè)值類型的數(shù)據(jù)
	// 實(shí)例化一個(gè)結(jié)構(gòu)體
	// 實(shí)例化的時(shí)候,可以只初始化部分?jǐn)?shù)據(jù)
	zrp := Student{
		id:     1,
		name:   "zrp",
	} 

    // 結(jié)構(gòu)體指針
	mc := &Student{
		id: 4,
		name: "mc",
	}

    // 使用結(jié)構(gòu)體方法
    // 值結(jié)構(gòu)(普通結(jié)構(gòu)體)
	// 普通結(jié)構(gòu):外面的數(shù)據(jù)和函數(shù)中的數(shù)據(jù)是兩個(gè)不同的數(shù)據(jù),在函數(shù)內(nèi)修改,不影響函數(shù)外
	zrp.changeSchool("湖南農(nóng)業(yè)大學(xué)")
	fmt.Printf("新學(xué)校是:%v\n", zrp.school)
    // 輸出為:新學(xué)校是: (沒有傳入值)

    // 指針結(jié)構(gòu)體:外面和函數(shù)中是同一個(gè)數(shù)據(jù),在函數(shù)中修改了,影響函數(shù)外
	mc.changeSchool2("湖南農(nóng)業(yè)大學(xué)")
	fmt.Printf("新學(xué)校是:%v\n", mc.school)

}

輸出:
新學(xué)校是:
新學(xué)校是:湖南農(nóng)業(yè)大學(xué)

四、結(jié)構(gòu)體繼承:

package main

import "fmt"

// 創(chuàng)建Author作者結(jié)構(gòu)體
type Author struct{
    // 定義字段
	name, tel string
	age int
}

// 繼承:Book繼承了Author結(jié)構(gòu)體
type Book struct {
	title string
	author Author
}

// 給Book添加了一個(gè)結(jié)構(gòu)體方法
func (b *Book) Print(){  
	fmt.Printf("%s的作者是:%s\n", b.title, b.author.name)
}

func main(){
	// 實(shí)例化方法
    // 先實(shí)例化Book,在將Author繼承給Book
	b1 := Book{title: "《Go入門到精通》"}
	b1.author.name = "TeacherWen"
	b1.author.tel = "187xxxxxxx"
	fmt.Printf("%+v\n",b1)
	b1.Print()

	// 先實(shí)例化Author, 再把Author賦值給Book
	a1 := Author{name: "TeacherFeng"}
	b2 := Book{title: "《Docker從入門到精通》", author: a1}
	fmt.Printf("%+v\n",b2)
	b2.Print()
}

輸出:
{title:《Go入門到精通》 author:{name:TeacherWen tel:187xxxxxxx age:0}}
《Go入門到精通》的作者是:TeacherWen
{title:《Docker從入門到精通》 author:{name:TeacherFeng tel: age:0}}
《Docker從入門到精通》的作者是:TeacherFeng

五、結(jié)構(gòu)體多態(tài):(interface接口的運(yùn)用)

多態(tài):一個(gè)接口多個(gè)形態(tài)(為多個(gè)不同的數(shù)據(jù)類型提供統(tǒng)一的接口)
????????其實(shí)就是一個(gè)功能,展現(xiàn)多種形態(tài)
????????多態(tài)是指同一種操作或方法可以在不同的對(duì)象上產(chǎn)生不同的行為。

Go語言中實(shí)現(xiàn)多態(tài)需要用到interface

Interface接口類型可以定義一組方法(而非變量),并且不需要實(shí)現(xiàn)


// 定義一個(gè)函數(shù)MyPrint,我們可以通過MyPrint來使多個(gè)數(shù)據(jù)進(jìn)行打印操作,但是當(dāng)前MyPrint并不是多態(tài)的,需要下面的interface接口操作
// func MyPrint(s string){
// 	 fmt.Println("")
// }


// 如果WePay結(jié)構(gòu)體實(shí)現(xiàn)了PayInterface接口所有的方法,那么可以說
// WePay結(jié)構(gòu)是是PayInterface類型
type PayInterface interface {
	// 聲明一些方法,但不需要實(shí)現(xiàn)
	// 方法名(參數(shù)列表) 返回值 --》pay()就為方法接口,他沒有參數(shù)和返回值
	pay()
    // 可以定義多個(gè)方法接口
    // pay2()、

    // print()
    // 運(yùn)行print()方法后報(bào)錯(cuò):AliPay does not implement PayInterface (missing print method) 和 WePay does not implement PayInterface (missing print method)
    // 說明AliPay 和 WePay 沒有實(shí)現(xiàn)print() 方法
    // 如果說WePay結(jié)構(gòu)體和AliPay結(jié)構(gòu)體實(shí)現(xiàn)了PayInterface接口所有的方法,那么可以說這個(gè)結(jié)構(gòu)體是PayInterface的可以實(shí)現(xiàn)的接口類型。

// 下面我們將要實(shí)現(xiàn)微信支付和支付寶支付操作

// 定義微信支付結(jié)構(gòu)體
type WePay struct {
	name string
}

// WePay實(shí)現(xiàn)了pay方法 等于  WePay實(shí)現(xiàn)PayInterface接口(wepay可以看作是PayInterface類型(上面定義的interface接口類型結(jié)構(gòu)體))
func (w WePay) pay(){
	fmt.Printf("This is WePay:%s\n", w.name)
}

// 定義支付寶支付結(jié)構(gòu)體
type  AliPay struct {
	name string
}

// AliPay實(shí)現(xiàn)PayInterface接口
func (a AliPay) pay(){
	fmt.Printf("This is AliPay:%s\n", a.name)
}

// 定義函數(shù)payment用于實(shí)現(xiàn)PayInterface接口的pay()方法
func payment(p PayInterface){
	p.pay()
}

func main(){
    // 實(shí)例化w1 和 a1,分別用于微信支付和支付寶支付
	w1 := WePay{name: "cici"}
	a1 := AliPay{name: "aiai"}
    // 調(diào)用payment函數(shù)傳入實(shí)例,實(shí)現(xiàn)WePay和AliPay 
	payment(w1)
	payment(a1)
}

輸出:
This is WePay:cici
This is AliPay:aiai

1、空接口的定義:

空接口可以表示任意類型的值。空接口的作用在于可以在不確定類型的情況下,用于保存和傳遞各種不同類型的值。由于空接口可以表示任意類型的值,所以它在某些場(chǎng)景下非常有用,比如在函數(shù)參數(shù)中,可以接受不同類型的參數(shù),或者在數(shù)據(jù)結(jié)構(gòu)中,可以存儲(chǔ)不同類型的元素。

package main

import "fmt"

// 空接口
type Empty interface {}

// 該test函數(shù)可以接收任意類型的數(shù)據(jù),空接口的定義方式
func test(f interface{}){
	fmt.Printf("%v\n",f)
}

func main(){
	// 空接口的使用
	// 該實(shí)例希望它的方法是string類型,但是它的value值可以是任意類型的,如希望m1定義為:m1 = {"name":"cici", "age":20}這種value可以是任意類型的,因此我們可以定義一個(gè)空接口Empty interface
	// Empty結(jié)構(gòu)體定義方式
	m1 :=map[string]Empty{
		"name":"cici",
		"age": 20,
	}

	//interface{}方法定義方式
	m2 :=map[string]interface{}{
		"name":"aiai",
		"age": "18",
	}
	fmt.Printf("%v\n%v\n", m1, m2)
}

輸出:
map[age:20 name:cici]
map[age:18 name:aiai]

2、接口如何實(shí)現(xiàn)自定義error呢?

package main

import (

	"fmt"
    //"errors"
)

// 定義NameCheck函數(shù),用于返回Error使用
// 如果name值為空,返回一個(gè)錯(cuò)誤,否則就返回nil
func NameCheck(name string) error {  // 返回?cái)?shù)據(jù)的類型是error類型
	if name == ""{
		// return errors.New("名字不能為空") // 通過errors包內(nèi)New函數(shù)來進(jìn)行error的提示, 比較復(fù)雜
		// 輸出為:名字不能為空

		// 進(jìn)行自定義錯(cuò)誤(優(yōu)點(diǎn)是比errors包內(nèi)調(diào)用New方法簡(jiǎn)單快捷很多)
		return NameEmptyError{msg:"名字不能為空", code:1001}
		// 輸出為:出錯(cuò)了:名字不能為空
	}
	return nil
}

// 自定義錯(cuò)誤 => 給NameEmptyError實(shí)現(xiàn)一個(gè)Error方法,它就是一個(gè)error類型了
type NameEmptyError struct {
	msg string
	code int
}

// 定義NameEmptyError結(jié)構(gòu)體方法Error()
func (e NameEmptyError) Error() string{
	// e.msg表示錯(cuò)誤的信息
	return "出錯(cuò)了:"+e.msg
}

func main(){
	// 定義變量name
	name := ""

	// 調(diào)用NameCheck函數(shù)
	err := NameCheck(name)
	if err != nil{
		// 出現(xiàn)錯(cuò)誤,輸出錯(cuò)誤
		fmt.Println(err)
	}else{
		fmt.Println(name)
	}
}

1、練習(xí):判斷Role(角色)是否存活

定義Role(角色) => 屬性:name, blood, isAlive(是否存活)

? ? ? ? ? ? ? ? ? ? ???isAlive => 判斷blood是<=0 True or False

package main

import "fmt"

// 定義結(jié)構(gòu)體
type Role struct {
	name string
	blood int
}

// 非指針型的綁定(將r 綁定為 Role 結(jié)構(gòu)體) isAlive() 是一個(gè)函數(shù)
func (r Role) isAlive() bool{
	if r.blood <= 0{
		return false
	}else{
		return true
	}
}

// 指針型的綁定
//func (r *Role) isAlive() bool {
//	if r.blood <= 0{
//		return false
//	}else{
//		return true
//	}
//}

func main(){
	// 創(chuàng)建實(shí)例類型
	role1 := Role{"role1", 90}
	role2 := Role{"role2", 0}
	// 打印數(shù)據(jù)
	fmt.Printf("%s:%v\n", role1.name, role1.isAlive())
	fmt.Printf("%s:%v\n", role2.name, role2.isAlive())
}

輸出:
role1:true
role2:false

2、練習(xí):實(shí)現(xiàn)發(fā)郵件功能

功能介紹:

普通用戶:結(jié)構(gòu)體User => 字段:username, email, ShowUserInfo(), SendMail()

Root用戶:結(jié)構(gòu)體Root => 字段:username, email, ShowSysInfo(), SendMail()

郵件告警的功能 => sendNotification函數(shù) --》可以接受所有權(quán)限用戶

普通用戶User和Root用戶都能夠使用sendNotification函數(shù)?=> 并實(shí)現(xiàn)對(duì)對(duì)象的SendMail()

package main

import "fmt"

// 定義User結(jié)構(gòu)體,內(nèi)存字段username(用戶名)、email(郵件地址)
type User struct {
	username string
	email string
}

// 定義Root結(jié)構(gòu)體,內(nèi)存字段username(用戶名)、email(郵件地址)
type Root struct {
	username string
	email string
}

// 定義ShowUserInfo()結(jié)構(gòu)體方法,調(diào)用User結(jié)構(gòu)體,實(shí)現(xiàn)展示用戶信息的功能
func (u User) ShowUserInfo(){
	fmt.Println("這是User的userInfo, User為:", u.username)
}

// 定義SendMail()結(jié)構(gòu)體方法,調(diào)用User結(jié)構(gòu)體,實(shí)現(xiàn)發(fā)送用戶郵件的功能
func (u User) SendMail(){
	fmt.Printf("User:%s正在發(fā)送郵件到%s\n", u.username, u.email)
}

// 定義ShowSysInfo()結(jié)構(gòu)體方法,調(diào)用Root結(jié)構(gòu)體,實(shí)現(xiàn)展示Root信息的功能
func (r Root) ShowSysInfo(){
	fmt.Println("這是Root的sysInfo, Root為:", r.username)
}

// 定義SendMail()結(jié)構(gòu)體方法,調(diào)用Root結(jié)構(gòu)體,實(shí)現(xiàn)Root發(fā)送郵件的功能
func (r Root) SendMail(){
	fmt.Printf("Root:%s正在發(fā)送郵件到%s\n", r.username, r.email)
}

// 定義SendMailInterface結(jié)構(gòu)體,內(nèi)存SendMail()結(jié)構(gòu)體方法
type SendMailInterface interface {
	SendMail()
}

// 定義sendNotification函數(shù),作用是接收參數(shù)并作為SendMail的對(duì)象
func sendNotification(s SendMailInterface){
	s.SendMail()
}


func main()  {
	// 結(jié)構(gòu)體實(shí)例化
	r := Root{username: "root", email: "root@sc.com"}
	u := User{username: "user1", email: "user1@sc.com"}
	// 調(diào)用sendNotification函數(shù),并傳入實(shí)例參數(shù)
	r.ShowSysInfo()
	sendNotification(r)
	u.ShowUserInfo()
	sendNotification(u)
}

輸出:
這是Root的sysInfo, Root為: root
Root:root正在發(fā)送郵件到root@sc.com
這是User的userInfo, User為: user1
User:user1正在發(fā)送郵件到user1@sc.com

3、練習(xí):定義標(biāo)準(zhǔn)化返回(json格式)

/*
// 定義返回的數(shù)據(jù)格式,將返回的數(shù)據(jù)用json的方式打印出來
// Code, Message, Data
// s.json() => 將它轉(zhuǎn)換成json格式(string)

后端開發(fā):API => 訪問url => 返回?cái)?shù)據(jù)(無頁(yè)面) => 訪問者
標(biāo)準(zhǔn)化返回:
{
	”code": 1001,
	"message": "參數(shù)不完整“,
	"data": {}/[]/other
}
*/

package main

import (
	"bufio"
	"encoding/json"
	"fmt"
	"os"
)

//標(biāo)準(zhǔn)化返回的結(jié)構(gòu)
type Response struct {
	Code int  `json:"code"`
	Message string  `json:"message"`
	Data interface{} `json:"data"`
}
// 從后端獲取數(shù)據(jù),將其變?yōu)闃?biāo)準(zhǔn)化的結(jié)構(gòu)
func Getdata() Response {
	code := 1001
	message := "參數(shù)不完整"
	data := map[string]interface{}{
		"name": "North",
		"sex": "male",
		"age": "21",
		"email":"north.12468@gmail.com",
	}
	// 創(chuàng)建實(shí)例
	res := Response{
		Code: code,
		Message: message,
		Data: data,
	}
	return res
}

func main()  {
	filepath := "./暑假開發(fā)/2023-08-01-go結(jié)構(gòu)體/data.json"
	result := Getdata()
	// 將后端的數(shù)據(jù)轉(zhuǎn)換為json格式
	jsonresult,err := json.Marshal(result)
	if err != nil {
		fmt.Println("json錯(cuò)誤:",err)
		return
	}else {
		//直接輸出
		fmt.Println(string(jsonresult))

		//寫入data.json文件中
		file,err1 := os.OpenFile(filepath,os.O_RDONLY|os.O_WRONLY,0666)
		if err1 != nil {
			fmt.Println("打開文件失敗")
		}
		defer file.Close()
		write := bufio.NewWriter(file)
		write.WriteString("\n")
		write.WriteString(string(jsonresult))
		write.Flush()
	}
}
type ResponseData struct {
	Code	int		`json:"code"`
	Message	string	`json:"message"`
	Data	interface{}	`json:"data"`
}
func (r ResponseData) json() (string, error){
	data, err := json.Marshal(r)
	return string(data), err
}
func main(){
	r := ResponseData{1001, "失敗了", ""}
	data, err := r.json()
	fmt.Printf("數(shù)據(jù):%v,錯(cuò)誤:%v\n", data, err)
}

?文章來源地址http://www.zghlxwxcb.cn/news/detail-622018.html

到了這里,關(guān)于go 結(jié)構(gòu)體 - 值類型、引用類型 - 結(jié)構(gòu)體轉(zhuǎn)json類型 - 指針類型的種類 - 結(jié)構(gòu)體方法 - 繼承 - 多態(tài)(interface接口) - 練習(xí)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 【30天熟悉Go語言】6 Go 復(fù)雜數(shù)據(jù)類型之指針

    【30天熟悉Go語言】6 Go 復(fù)雜數(shù)據(jù)類型之指針

    Go系列文章: GO開篇:手握J(rèn)ava走進(jìn)Golang的世界 2 Go開發(fā)環(huán)境搭建、Hello World程序運(yùn)行 3 Go編程規(guī)約和API包 4 Go的變量、常量、運(yùn)算符 5 Go 基本數(shù)據(jù)類型 Go專欄傳送鏈接:https://blog.csdn.net/saintmm/category_12326997.html 和 C/C++ 中的指針不同,Go中的指針不能進(jìn)行偏移和運(yùn)算。它是一種類型

    2024年02月09日
    瀏覽(24)
  • 【c++速通】入門級(jí)攻略:引用詳解 | auto的類型推導(dǎo) | 不一樣的for循環(huán) | nullptr版本空指針

    【c++速通】入門級(jí)攻略:引用詳解 | auto的類型推導(dǎo) | 不一樣的for循環(huán) | nullptr版本空指針

    ?? 嶼小夏 : 個(gè)人主頁(yè) ??個(gè)人專欄 : C++入門到進(jìn)階 ?? 莫道桑榆晚,為霞尚滿天! 上篇文章中,對(duì)函數(shù)重載和內(nèi)聯(lián)函數(shù)的作用和特性使用,進(jìn)行了精細(xì)的詳解。 引用和指針混不清?引用的抽絲剝繭!還有不用寫類型可以自動(dòng)推導(dǎo)的?for遍歷竟然還有我們沒見過的面

    2024年02月08日
    瀏覽(19)
  • 深入解析Go非類型安全指針:技術(shù)全解與最佳實(shí)踐

    深入解析Go非類型安全指針:技術(shù)全解與最佳實(shí)踐

    本文全面深入地探討了Go非類型安全指針,特別是在Go語言環(huán)境下的應(yīng)用。從基本概念、使用場(chǎng)景,到潛在風(fēng)險(xiǎn)和挑戰(zhàn),文章提供了一系列具體的代碼示例和最佳實(shí)踐。目的是幫助讀者在保證代碼安全和效率的同時(shí),更加精通非類型安全指針的使用。 關(guān)注【TechLeadCloud】,分享

    2024年02月08日
    瀏覽(22)
  • C++ 引用和指針:內(nèi)存地址、創(chuàng)建方法及應(yīng)用解析

    引用變量是對(duì)現(xiàn)有變量的“別名”,它是使用 運(yùn)算符創(chuàng)建的: 現(xiàn)在,我們可以使用變量名 food 或引用名 meal 來引用食物變量: 內(nèi)存地址 在前一頁(yè)的示例中,使用 運(yùn)算符創(chuàng)建了一個(gè)引用變量。但它也可以用于獲取變量的內(nèi)存地址;即變量在計(jì)算機(jī)上存儲(chǔ)的位置。 當(dāng)在 C++ 中

    2024年04月11日
    瀏覽(26)
  • Golang struct 結(jié)構(gòu)體指針類型 / 結(jié)構(gòu)體值類型

    Golang struct 結(jié)構(gòu)體指針類型 / 結(jié)構(gòu)體值類型

    結(jié)構(gòu)體變量之間的賦值是值拷貝。 當(dāng)需要通過變量去修改另外一個(gè)結(jié)構(gòu)體內(nèi)容的時(shí)候,可以通過傳遞地址的方式來達(dá)到這個(gè)效果。 這樣使用肯定是不對(duì)的,因?yàn)?的運(yùn)算優(yōu)先級(jí)要高,所以先會(huì)去執(zhí)行p2.age,之后又取地址,所以這個(gè)就不行。 在代碼執(zhí)行的時(shí)候先執(zhí)行.的操作,

    2024年02月13日
    瀏覽(24)
  • C# 使用SIMD向量類型加速浮點(diǎn)數(shù)組求和運(yùn)算(4):用引用代替指針, 擺脫unsafe關(guān)鍵字,兼談Unsafe類的使用

    作者: zyl910 目錄 一、引言 二、辦法說明 2.1 歷史 2.2 局部引用變量與引用所指的值(類似指針的 地址運(yùn)算符 、間接運(yùn)算符 * ) 2.3 重新分配局部引用變量(類似指針直接賦值) 2.4 引用地址調(diào)整(類似指針加減法) 2.5 引用地址比較(類似指針比較) 2.6 重新解釋(類似C++的

    2024年02月15日
    瀏覽(21)
  • C語言——結(jié)構(gòu)體類型(一)【結(jié)構(gòu)體定義,創(chuàng)建,初始化和引用】

    C語言——結(jié)構(gòu)體類型(一)【結(jié)構(gòu)體定義,創(chuàng)建,初始化和引用】

    ??前言: 在實(shí)際編程過程中,我們可能會(huì)希望把一些關(guān)聯(lián)的數(shù)據(jù)存放在一起,這樣方便我們使用。但是這些數(shù)據(jù)的類型有時(shí)候并不一致,例如一個(gè)學(xué)生的信息:有名字(字符串),有年齡(整數(shù)),性別(字符)······這時(shí)候,我們就可以使用 自定義類型——結(jié)構(gòu)體類型

    2024年02月03日
    瀏覽(35)
  • Python史上最全種類數(shù)據(jù)庫(kù)操作方法,你能想到的數(shù)據(jù)庫(kù)類型都在里面!甚至還有云數(shù)據(jù)庫(kù)!

    本文將詳細(xì)探討如何在Python中連接全種類數(shù)據(jù)庫(kù)以及實(shí)現(xiàn)相應(yīng)的CRUD(創(chuàng)建,讀取,更新,刪除)操作。我們將逐一解析連接MySQL,SQL Server,Oracle,PostgreSQL,MongoDB,SQLite,DB2,Redis,Cassandra,Microsoft Access,ElasticSearch,Neo4j,InfluxDB,Snowflake,Amazon DynamoDB,Microsoft Azure CosMos DB數(shù)

    2024年02月12日
    瀏覽(46)
  • C語言自定義數(shù)據(jù)類型(三)結(jié)構(gòu)體指針

    C語言自定義數(shù)據(jù)類型(三)結(jié)構(gòu)體指針

    所謂結(jié)構(gòu)體指針就是指向結(jié)構(gòu)體變量的指針,一個(gè)結(jié)構(gòu)體變量的起始地址就是這個(gè)結(jié)構(gòu)體變量的指針。如果把一個(gè)結(jié)構(gòu)體變量的起始地址存放在一個(gè)指針變量中,那么,這個(gè)指針變量就指向該結(jié)構(gòu)體變量。 目錄 一、指向結(jié)構(gòu)體變量的指針 1.1舉例說明 二、指向結(jié)構(gòu)體數(shù)組的指

    2024年02月06日
    瀏覽(17)
  • 包含引用類型字段的自定義結(jié)構(gòu)體,能作為map的key嗎

    在 Go 語言中, map 是一種內(nèi)置的數(shù)據(jù)類型,它提供了一種高效的方式來存儲(chǔ)和檢索數(shù)據(jù)。 map 是一種無序的鍵值對(duì)集合,其中每個(gè)鍵與一個(gè)值相關(guān)聯(lián)。使用 map 數(shù)據(jù)結(jié)構(gòu)可以快速地根據(jù)鍵找到對(duì)應(yīng)的值,而無需遍歷整個(gè)集合。 在 Go 語言中, map 是一種內(nèi)置的數(shù)據(jù)類型,可以通

    2024年02月07日
    瀏覽(24)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包