目錄
一、結(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è)字段,分別為Name
和Age
,分別用來存儲(chǔ)人的姓名和年齡。在
main
函數(shù)中,我們創(chuàng)建了兩個(gè)Person
類型的變量person1
和person2
,并分別設(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:
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格式
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()文章來源:http://www.zghlxwxcb.cn/news/detail-622018.html
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)!