Go結(jié)構(gòu)-2

指針

普通指針

  1. 通過指針也可以間接操作指向的存儲空間
格式:var p *int

var num int = 666
var value float32 = 3.14
var flag bool = false

var p1 *int
p1 = &num
fmt.Println(num)
*p1 = 678
fmt.Println(num)


var p2 *float32 = &value
fmt.Println(value)
*p2 = 6.66
fmt.Println(value)

p3 := &flag
fmt.Println(flag)
*p3 = true
fmt.Println(flag)

指向數(shù)組的指針

  1. 可以通過指針間接操作數(shù)組
格式:var p *[3]int
操作數(shù)組:(*p)[0] / p[0]

var arr [3]int = [3]int{1, 3, 5}
var p *[3]int
p = &arr
//p = &arr[0] //數(shù)據(jù)類型不同,不能賦值
(*p)[0] = 666
p[0] = 666
  1. 注意點:
    1. Go語言中 &數(shù)組名/&數(shù)組首元素 都是同意哦個地址,但是通過數(shù)組名不能直接獲取數(shù)組的地址(C語言中可以)
    2. 只有相同類型的數(shù)據(jù)才能賦值
    3. 指向數(shù)組的指針不支持+1 -1操作

指向切片的指針

  1. 切片的本質(zhì)是結(jié)構(gòu)體,結(jié)構(gòu)體的一個屬性是指針,這個指針指向了底層的一個數(shù)組
操作切片:(*p)[0]

sce := []int{1, 3, 5}
//打印sce,得到的是結(jié)構(gòu)體中指向底層數(shù)組的指針保存的值
//fmt.Printf("sce = %T\n",sce) // []int
//打印&sce,得到的是切片結(jié)構(gòu)自己的地址
//fmt.Printf("&sce = %T\n",&sce) // *[]int


var p *[]int
p = &sce
//結(jié)論: p == &sce / *p == sce
(*p)[0] = 666
sce[0] = 678
p[0] =888 // 報錯

指向字典的指針

操作字典: (*p)[key]

dict := map[string]string{"name":"yzf", "age":"18"}
var p *map[string]string
p = &dict
(*p)["name"] = "zx"
dict["name"] = "zs"
p["name"] = "ww" //報錯

指向結(jié)構(gòu)體的指針

  1. 和C語言一樣
操作結(jié)構(gòu)體: (*p).atter 和 p.atter

type Person struct {
        name string
        age int
}
var per Person = Person{"yzf", 18}
var p *Person
p = &per
(*p).name = "zs"
p.name = "zs"

指針作為函數(shù)的參數(shù)和返回值

  1. 地址傳遞
  2. 若指針指向的是一個局部變量,不建議返回(函數(shù)調(diào)用完后局部變量就釋放)

方法

方法的基本使用

  1. 方法就是一個特殊的函數(shù),函數(shù)獨立存在,方法和某種數(shù)據(jù)類型綁定在一起的
  2. 格式:
func (接收者名稱 接收者類型)函數(shù)名(形參列表)(返回值列表){
    邏輯語句
}
  1. Go語言的函數(shù)可以和任何類型綁定,但一般用于和結(jié)構(gòu)體綁定
  2. 注意:
    1. 方法和函數(shù)的區(qū)別:函數(shù)可以==直接調(diào)用(包名.函數(shù)名)==,方法只能==通過綁定的數(shù)據(jù)類型對應(yīng)的變量來調(diào)用(變量.函數(shù)名)==
    2. 函數(shù)名和方法名可以重名
    3. 方法和函數(shù)都是函數(shù)類型
//1.定義一個結(jié)構(gòu)體
type Person struct {
    name string
    age int
}
//2.定義一個方法,和Person結(jié)構(gòu)體綁定
//如果指定了接收者的名稱,那么調(diào)用方法時會將調(diào)用者傳遞給接收者
func (per Person)say() {
    fmt.Println("name is", per.name, "age is", per.age)
}
3.接收者存在值傳遞和地址傳遞的問題
//值傳遞
func (per Person)setName(name string) {
    per.name = name
}
//地址傳遞 
//只要接收者是指針類型,編譯器會自動將普通變量的地址取出來傳遞給接收者
func (per *Person)setAge(age int) {
    (*per).age = age
}
func say() {
    fmt.Println("hello")
}

p := Person{name:"yzf", age:18}
var ptr *Person = &p
//ptr.setName("zx")// 值傳遞
ptr.setAge(20)
p.say() //方法調(diào)用

say() //函數(shù)調(diào)用

接口

接口的基本使用

  1. 定義某種規(guī)范,只要使用者按照接口定義的標(biāo)準(zhǔn)來實現(xiàn),無論誰實現(xiàn)都可以使用
  2. 作用:用于定義函數(shù)的聲明(規(guī)定函數(shù)的形參,返回值,名稱)
  3. 格式
type 接口名稱 interface{
    函數(shù)的聲明
}
  1. 注意點:
    1. 接口只有方法的聲明,沒有方法的實現(xiàn)
    2. 接口中聲明的方法,==只能通過和某種數(shù)據(jù)類型綁定的方法實現(xiàn)==,不能通過函數(shù)實現(xiàn)
    3. 只要某個數(shù)據(jù)類型實現(xiàn)了接口中聲明的==所有==方法,就可以說這個數(shù)據(jù)類型實現(xiàn)了這個接口
    4. 一個數(shù)據(jù)類型實現(xiàn)了某個接口,就可以使用這個接口類型的變量來保存這個類型的數(shù)據(jù),也可以使用接口類型變量調(diào)用接口中的方法
//1.定義一個接口
type USB interface {
    //制定一個方法的標(biāo)準(zhǔn)
    //名稱是start,傳入?yún)?shù)類型為string,沒返回值
    start(name string)
    //名稱是end,傳入?yún)?shù)類型為string,沒返回值
    end(name string)
}

type Computer struct{
}
//實現(xiàn)接口中聲明的方法
func (Computer)start(name string) {
    fmt.Println(name, "啟動了")
}
func (Computer)end(name string) {
    fmt.Println(name, "關(guān)機了")
}

type Phone struct {
    
}
//實現(xiàn)接口中聲明的方法
func (Phone)start(name string) {
    fmt.Println(name, "啟動了")
}
func (Phone)end(name string) {
    fmt.Println(name, "關(guān)機了")
}
func main() {
    cm := Computer{}
    Option(cm, "DELL")
    pp := Phone{}
    Option(pp, "huawei")
    
    
}
//函數(shù)的作用,開關(guān)
func Option(in USB, name string) {
    in.start(name)
    in.end(name)
}
  1. ==重點掌握==:
1.定義一個接口
type USB interfa {
    函數(shù)名(形參列表)(返回值列表)
    函數(shù)名(形參列表)(返回值列表)
}

2.實現(xiàn)一個接口
只要某種數(shù)據(jù)類型綁定了所有接口中聲明的方法就是實現(xiàn)了這個接口

3.實現(xiàn)接口后的特性
(1)只要某種數(shù)據(jù)類型實現(xiàn)了接口,那么就可以使用接口變量保存這種數(shù)據(jù)類型
(2)只要某種數(shù)據(jù)類型實現(xiàn)了接口,那么就可以使用接口變量調(diào)用接口中聲明的方法

接口的注意點

  1. 接口中只能有方法的聲明,==不能有方法的實現(xiàn)和變量的聲明==
  2. 只有實現(xiàn)了接口中聲明的所有方法,才算實現(xiàn)了接口,才算實現(xiàn)了接口,才能使用接口變量保存
  3. 實現(xiàn)接口時,方法名,形參列表,返回值必須一模一樣
  4. 接口和結(jié)構(gòu)體一樣,可以嵌套(不能自己嵌套自己)
  5. 可以將超集接口變量賦值給子集接口變量,不可以講子集接口變量賦值給超集接口變量(無論實際數(shù)據(jù)類型是否實現(xiàn)了超集的所有方法)
//子集接口
type aer interface {
    // aer //會報錯
    start()
}
//超集接口
type ber interface {
    aer //在ber中嵌套了aer
    end()
}
type Phone struct {
    name string
}

func (p Phone)start() {
    fmt.Println(p.name, "啟動了")
}
func (p Phone)end() {
    fmt.Println(p.name, "關(guān)閉了")
}
func main() {
    var b ber = Phone{"華為"}
    var a aer 
    a = b //可以賦值
    a.start()
    
    /*
    var a aer = Phone{"華為"}
    var b ber
    b = a //會報錯
    */
}
  1. 接口中不能出現(xiàn)同名的方法聲明

空接口

  1. Go語言中的空接口,相當(dāng)于其他語言的Object類型
  2. Go語言中的空接口,可以充當(dāng)任何類型
  3. 格式: interfa{}
  4. 有了空接口,可以讓數(shù)組和字典保存不同類型的數(shù)據(jù)
  5. 注意:空接口類型的數(shù)據(jù)和普通的數(shù)據(jù)類型,在使用時有很大區(qū)別的
    var value interface{}
    value = 1 // 保存整型
    value = 3.14 // 保存浮點類型
    value = false // 保存布爾類型
    value = 'T' // 保存字符
    value = "lnj" // 保存字符串類型
    value = [3]int{1, 3, 5} // 保存數(shù)組類型
    value = []int{2, 4, 5} // 保存切片類型
    value = map[string]string{"name": "lnj", "age": "18"} // 保存字典類型
    value = Person{"lnj", 33} // 保存結(jié)構(gòu)體類型
    
     // 1.定義一個數(shù)組
     var arr [3]interface{}
     // 2.往數(shù)組中存儲數(shù)據(jù)
     arr[0] = 1
     arr[1] = "lnj"
     arr[2] = false
     // 3.打印數(shù)據(jù)
     fmt.Println(arr)

接口類型的轉(zhuǎn)換

  1. 如果結(jié)構(gòu)體實現(xiàn)了某個接口,那么就可以使用接口類型來保存結(jié)構(gòu)體變量
  2. 如果利用接口類型變量保存了實現(xiàn)了接口的結(jié)構(gòu)體,那么該變量只能訪問接口中的方法,不能訪問結(jié)構(gòu)體中特有的方法,以及結(jié)構(gòu)體中的屬性
  3. 如果利用結(jié)構(gòu)類型變量保存了實現(xiàn)了結(jié)構(gòu)的結(jié)構(gòu)體,想要訪問結(jié)構(gòu)體中特有的方法和屬性,那么必須進行類型轉(zhuǎn)換,將接口類型轉(zhuǎn)換為結(jié)構(gòu)體類型
type USB interface {
    start()
}
type Computer struct {
    name string
}
func (cm Computer)start() {
    fmt.Println(cm.name, "啟動了")
}
func (cm Computer)say() {
    fmt.Println(cm.name)
}
func main() {
    var in USB = Computer{"huawei"}
}
in.start() 
//in.say() //報錯
//fmt.Println(in.name) //報錯

//類型轉(zhuǎn)換
//方法一:使用類型斷言
//格式: cm, ok := 接口類型變量名.(結(jié)構(gòu)體類型)
cm, ok := in.(Computer)
fmt.Println(cm.name)
fmt.Println(ok)
//if cm, ok := in.(Computer); ok{
//  cm.say()
//  fmt.Println(cm.name)
//}

//方式二:使用類型斷言
//會將接口類型變量轉(zhuǎn)換為對應(yīng)的原始類型之后賦值給cm
//格式:cm := 接口變量名.(type)
switch cm := in.(type) {
    case Computer:
        fmt.Println(cm)
        cm.say()
    default:
        fmt.Println("不是Computer")
        
}

cm := Computer{"惠普"}
var sce []interface{} = []interface{}{1, 3.14, false, "lnj", cm}
// 需求: 獲取切片中保存的每一個數(shù)據(jù)的原始類型
for key, value := range sce {
    switch temp := value.(type) {
    case int:
        fmt.Println("第",key, "個元素是int類型")
    case float64:
        fmt.Println("第",key, "個元素是float64類型")
    case bool:
        fmt.Println("第",key, "個元素是bool類型")
    case string:
        fmt.Println("第",key, "個元素是string類型")
    case Computer:
        fmt.Println("第",key, "個元素是Computer類型")
        temp.say()
        }
        
//方法一除了可以將接口類型轉(zhuǎn)換為具體類型以外,還可以將抽象接口類型轉(zhuǎn)換為具體的接口類型
var in interface{}
in = Computer{"huawei"}
//in.start() //不可以利用抽象接口類型變量, 調(diào)用具體接口類型中聲明的方法
if value, ok := in.(USB); ok{
    value.start()
}
//或者
if value, ok := in.(Computer); ok{
    value.start()
}

別名

  1. 在C語言中可以通過typedef給某種類型起一個別名
格式: typedef 原類型名 新類型名;
  1. 在Go語言中可以通過type給某種類型起一個別名
格式一: type 新類型名 原類型名
//代表起了一個新的類型叫 新類型名(是兩個不同類型)
格式二: type 新類型名=原類型名
//代表給原類型名起了一個別名叫做 新類型名(是同一個類型)

//type newint int //報錯
type newint = int
num1 := 666
var num2 newint
num2 = num1
fmt.Println(num1,num2)


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末娃胆,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌讥巡,老刑警劉巖捏鱼,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件伙菜,死亡現(xiàn)場離奇詭異受楼,居然都是意外死亡甥角,警方通過查閱死者的電腦和手機网严,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來嗤无,“玉大人震束,你說我怎么就攤上這事〉狈福” “怎么了垢村?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長灶壶。 經(jīng)常有香客問我肝断,道長,這世上最難降的妖魔是什么驰凛? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任胸懈,我火速辦了婚禮,結(jié)果婚禮上恰响,老公的妹妹穿的比我還像新娘趣钱。我一直安慰自己,他們只是感情好胚宦,可當(dāng)我...
    茶點故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布首有。 她就那樣靜靜地躺著燕垃,像睡著了一般。 火紅的嫁衣襯著肌膚如雪井联。 梳的紋絲不亂的頭發(fā)上卜壕,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天,我揣著相機與錄音烙常,去河邊找鬼轴捎。 笑死,一個胖子當(dāng)著我的面吹牛蚕脏,可吹牛的內(nèi)容都是我干的侦副。 我是一名探鬼主播,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼驼鞭,長吁一口氣:“原來是場噩夢啊……” “哼秦驯!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起挣棕,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤译隘,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后穴张,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體细燎,經(jīng)...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年皂甘,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片悼凑。...
    茶點故事閱讀 38,566評論 1 339
  • 序言:一個原本活蹦亂跳的男人離奇死亡偿枕,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出户辫,到底是詐尸還是另有隱情渐夸,我是刑警寧澤,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布渔欢,位于F島的核電站墓塌,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏奥额。R本人自食惡果不足惜苫幢,卻給世界環(huán)境...
    茶點故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望垫挨。 院中可真熱鬧韩肝,春花似錦、人聲如沸九榔。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至剩蟀,卻和暖如春催蝗,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背育特。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工丙号, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人且预。 一個月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓槽袄,卻偏偏與公主長得像,于是被迫代替她去往敵國和親锋谐。 傳聞我的和親對象是個殘疾皇子遍尺,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,440評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 指針是C語言中廣泛使用的一種數(shù)據(jù)類型。 運用指針編程是C語言最主要的風(fēng)格之一涮拗。利用指針變量可以表示各種數(shù)據(jù)結(jié)構(gòu)乾戏; ...
    朱森閱讀 3,426評論 3 44
  • 這是16年5月份編輯的一份比較雜亂適合自己觀看的學(xué)習(xí)記錄文檔,今天18年5月份再次想寫文章三热,發(fā)現(xiàn)簡書還為我保存起的...
    Jenaral閱讀 2,737評論 2 9
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對...
    cosWriter閱讀 11,090評論 1 32
  • 前言 把《C++ Primer》[https://book.douban.com/subject/25708312...
    尤汐Yogy閱讀 9,511評論 1 51
  • 春節(jié)倒計時29天鼓择。又到了一年一度的績效考評,這一次我想到了一個詞語 - 金字塔的頂部就漾。當(dāng)一個人的績效要被你的上級唯...
    張公子在這等你閱讀 157評論 0 0