要判斷數據類型,可以用Go的空接口:
創新互聯是一家專注于網站設計制作、成都網站設計與策劃設計,谷城網站建設哪家好?創新互聯做網站,專注于網站建設十多年,網設計領域的專業建站公司;建站業務涵蓋:谷城等地區。谷城做網站價格咨詢:028-86922220
建一個函數t 設置參數i 的類型為空接口,空接口可以接受任何數據類型
func t(i interface{}) {
//函數t
有一個參數i
switch i.(type) {
//多選語句switch
case string:
//是字符時做的事情
case int:
//是整數時做的事情
}
return
}
i.(type)
只能在switch中使用
這函數沒有返回值,你可以自己加入
還可以用反射:
package main
import (
"fmt"
"reflect"
)
func main() {
var x float64 = 3.4
fmt.Println("type:", reflect.TypeOf(x))
}
這樣就可以得出變量x的類型信息,與上面不同的是:上面的方法要先知到它是幾個類型中的一個,而這個方法可以對任意對象使用
隊列的概念在 順序隊列 中,而使用循環隊列的目的主要是規避假溢出造成的空間浪費,在使用循環隊列處理假溢出時,主要有三種解決方案
本文提供后兩種解決方案。
順序隊和循環隊列是一種特殊的線性表,與順序棧類似,都是使用一組地址連續的存儲單元依次存放自隊頭到隊尾的數據元素,同時附設隊頭(front)和隊尾(rear)兩個指針,但我們要明白一點,這個指針并不是指針變量,而是用來表示數組當中元素下標的位置。
本文使用切片來完成的循環隊列,由于一開始使用三個參數的make關鍵字創建切片,在輸出的結果中不包含nil值(看起來很舒服),而且在驗證的過程中發現使用append()函數時切片內置的cap會發生變化,在消除了種種障礙后得到了一個四不像的循環隊列,即設置的指針是順序隊列的指針,但實際上進行的操作是順序隊列的操作。最后是對make()函數和append()函數的一些使用體驗和小結,隊列的應用放在鏈隊好了。
官方描述(片段)
即切片是一個抽象層,底層是對數組的引用。
當我們使用
構建出來的切片的每個位置的值都被賦為interface類型的初始值nil,但是nil值也是有大小的。
而使用
來進行初始化時,雖然生成的切片中不包含nil值,但是無法通過設置的指針變量來完成入隊和出隊的操作,只能使用append()函數來進行操作
在go語言中,切片是一片連續的內存空間加上長度與容量的標識,比數組更為常用。使用 append 關鍵字向切片中追加元素也是常見的切片操作
正是基于此,在使用go語言完成循環隊列時,首先想到的就是使用make(type, len, cap)關鍵字方式完成切片初始化,然后使用append()函數來操作該切片,但這一方式出現了很多問題。在使用append()函數時,切片的cap可能會發生變化,用不好就會發生擴容或收縮。最終造成的結果是一個四不像的結果,入隊和出隊操作變得與指針變量無關,失去了作為循環隊列的意義,用在順序隊列還算合適。
參考博客:
Go語言中的Nil
Golang之nil
Go 語言設計與實現
import "workname/packetfolder"
導入多個包
方法調用 包名.函數//不是函數或結構體所處文件或文件夾名
packagename.Func()
前面加個點表示省略調用,那么調用該模塊里面的函數,可以不用寫模塊名稱了:
當導入一個包時,該包下的文件里所有init()函數都會被執行,然而,有些時候我們并不需要把整個包都導入進來,僅僅是是希望它執行init()函數而已。下劃線的作用僅僅是為了調用init()函數,所以無法通過包名來調用包中的其他函數
import _ package
變量聲明必須要使用否則會報錯。
全局變量運行聲明但不使用。
func 函數名 (參數1,參數2,...) (返回值a 類型a, 返回值b 類型b,...)
func 函數名 (參數1,參數2,...) (返回值類型1, 返回值類型2,...)
func (this *結構體名) 函數名(參數 string) (返回值類型1, 返回值類型2){}
使用大小來區分函數可見性
大寫是public類型
小寫是private類型
func prifunc int{}
func pubfunc int{}
聲明靜態變量
const value int
定義變量
var value int
聲明一般類型、接口和結構體
聲明函數
func function () int{}
go里面所有的空值對應如下
通道類型
內建函數 new 用來分配內存,它的第一個參數是一個類型,不是一個值,它的返回值是一個指向新分配類型零值的指針
func new(Type) *Type
[這位博主有非常詳細的分析]
Go 語言支持并發,我們只需要通過 go 關鍵字來開啟 goroutine 即可。
goroutine 是輕量級線程,goroutine 的調度是由 Golang 運行時進行管理的。
同一個程序中的所有 goroutine 共享同一個地址空間。
語法格式如下:
通道(channel)是用來傳遞數據的一個數據結構。
通道的聲明
通道可用于兩個 goroutine 之間通過傳遞一個指定類型的值來同步運行和通訊。操作符 - 用于指定通道的方向,發送或接收。如果未指定方向,則為雙向通道。
[這里有比較詳細的用例]
go里面的空接口可以指代任何類型(無論是變量還是函數)
聲明空接口
go里面的的強制類型轉換語法為:
int(data)
如果是接口類型的強制轉成其他類型的語法為:
go里面的強制轉換是將值復制過去,所以在數據量的時候有比較高的運行代價
Go語言中沒有“類”的概念,也不支持“類”的繼承等面向對象的概念。Go語言中通過結構體的內嵌再配合接口比面向對象具有更高的擴展性和靈活性。
自定義類型
在Go語言中有一些基本的數據類型,如string、整型、浮點型、布爾等數據類型, Go語言中可以使用type關鍵字來定義自定義類型。
自定義類型是定義了一個全新的類型。我們可以基于內置的基本類型定義,也可以通過struct定義。例如:
通過Type關鍵字的定義,MyInt就是一種新的類型,它具有int的特性。
類型別名
類型別名是Go1.9版本添加的新功能。
類型別名規定:TypeAlias只是Type的別名,本質上TypeAlias與Type是同一個類型。就像一個孩子小時候有小名、乳名,上學后用學名,英語老師又會給他起英文名,但這些名字都指的是他本人。
type TypeAlias = Type
我們之前見過的rune和byte就是類型別名,他們的定義如下:
類型定義和類型別名的區別
類型別名與類型定義表面上看只有一個等號的差異,我們通過下面的這段代碼來理解它們之間的區別。
結果顯示a的類型是main.NewInt,表示main包下定義的NewInt類型。b的類型是int。MyInt類型只會在代碼中存在,編譯完成時并不會有MyInt類型。
Go語言中的基礎數據類型可以表示一些事物的基本屬性,但是當我們想表達一個事物的全部或部分屬性時,這時候再用單一的基本數據類型明顯就無法滿足需求了,Go語言提供了一種自定義數據類型,可以封裝多個基本數據類型,這種數據類型叫結構體,英文名稱struct。 也就是我們可以通過struct來定義自己的類型了。
Go語言中通過struct來實現面向對象。
結構體的定義
使用type和struct關鍵字來定義結構體,具體代碼格式如下:
其中:
舉個例子,我們定義一個Person(人)結構體,代碼如下:
同樣類型的字段也可以寫在一行,
這樣我們就擁有了一個person的自定義類型,它有name、city、age三個字段,分別表示姓名、城市和年齡。這樣我們使用這個person結構體就能夠很方便的在程序中表示和存儲人信息了。
語言內置的基礎數據類型是用來描述一個值的,而結構體是用來描述一組值的。比如一個人有名字、年齡和居住城市等,本質上是一種聚合型的數據類型
結構體實例化
只有當結構體實例化時,才會真正地分配內存。也就是必須實例化后才能使用結構體的字段。
基本實例化
舉個例子:
我們通過.來訪問結構體的字段(成員變量),例如p1.name和p1.age等。
匿名結構體
在定義一些臨時數據結構等場景下還可以使用匿名結構體。
創建指針類型結構體
我們還可以通過使用new關鍵字對結構體進行實例化,得到的是結構體的地址。 格式如下:
從打印的結果中我們可以看出p2是一個結構體指針。
需要注意的是在Go語言中支持對結構體指針直接使用.來訪問結構體的成員。
取結構體的地址實例化
使用對結構體進行取地址操作相當于對該結構體類型進行了一次new實例化操作。
p3.name = "七米"其實在底層是(*p3).name = "七米",這是Go語言幫我們實現的語法糖。
結構體初始化
沒有初始化的結構體,其成員變量都是對應其類型的零值。
使用鍵值對初始化
使用鍵值對對結構體進行初始化時,鍵對應結構體的字段,值對應該字段的初始值。
也可以對結構體指針進行鍵值對初始化,例如:
當某些字段沒有初始值的時候,該字段可以不寫。此時,沒有指定初始值的字段的值就是該字段類型的零值。
使用值的列表初始化
初始化結構體的時候可以簡寫,也就是初始化的時候不寫鍵,直接寫值:
使用這種格式初始化時,需要注意:
結構體內存布局
結構體占用一塊連續的內存。
輸出:
【進階知識點】關于Go語言中的內存對齊推薦閱讀:在 Go 中恰到好處的內存對齊
面試題
請問下面代碼的執行結果是什么?
構造函數
Go語言的結構體沒有構造函數,我們可以自己實現。 例如,下方的代碼就實現了一個person的構造函數。 因為struct是值類型,如果結構體比較復雜的話,值拷貝性能開銷會比較大,所以該構造函數返回的是結構體指針類型。
調用構造函數
方法和接收者
Go語言中的方法(Method)是一種作用于特定類型變量的函數。這種特定類型變量叫做接收者(Receiver)。接收者的概念就類似于其他語言中的this或者 self。
方法的定義格式如下:
其中,
舉個例子:
方法與函數的區別是,函數不屬于任何類型,方法屬于特定的類型。
指針類型的接收者
指針類型的接收者由一個結構體的指針組成,由于指針的特性,調用方法時修改接收者指針的任意成員變量,在方法結束后,修改都是有效的。這種方式就十分接近于其他語言中面向對象中的this或者self。 例如我們為Person添加一個SetAge方法,來修改實例變量的年齡。
調用該方法:
值類型的接收者
當方法作用于值類型接收者時,Go語言會在代碼運行時將接收者的值復制一份。在值類型接收者的方法中可以獲取接收者的成員值,但修改操作只是針對副本,無法修改接收者變量本身。
什么時候應該使用指針類型接收者
任意類型添加方法
在Go語言中,接收者的類型可以是任何類型,不僅僅是結構體,任何類型都可以擁有方法。 舉個例子,我們基于內置的int類型使用type關鍵字可以定義新的自定義類型,然后為我們的自定義類型添加方法。
注意事項: 非本地類型不能定義方法,也就是說我們不能給別的包的類型定義方法。
結構體的匿名字段
匿名字段默認采用類型名作為字段名,結構體要求字段名稱必須唯一,因此一個結構體中同種類型的匿名字段只能有一個。
嵌套結構體
一個結構體中可以嵌套包含另一個結構體或結構體指針。
嵌套匿名結構體
當訪問結構體成員時會先在結構體中查找該字段,找不到再去匿名結構體中查找。
嵌套結構體的字段名沖突
嵌套結構體內部可能存在相同的字段名。這個時候為了避免歧義需要指定具體的內嵌結構體的字段。
結構體的“繼承”
Go語言中使用結構體也可以實現其他編程語言中面向對象的繼承。
結構體字段的可見性
結構體中字段大寫開頭表示可公開訪問,小寫表示私有(僅在定義當前結構體的包中可訪問)。
結構體與JSON序列化
JSON(JavaScript Object Notation) 是一種輕量級的數據交換格式。易于人閱讀和編寫。同時也易于機器解析和生成。JSON鍵值對是用來保存JS對象的一種方式,鍵/值對組合中的鍵名寫在前面并用雙引號""包裹,使用冒號:分隔,然后緊接著值;多個鍵值之間使用英文,分隔。
結構體標簽(Tag)
Tag是結構體的元信息,可以在運行的時候通過反射的機制讀取出來。 Tag在結構體字段的后方定義,由一對反引號包裹起來,具體的格式如下:
`key1:"value1" key2:"value2"`
結構體標簽由一個或多個鍵值對組成。鍵與值使用冒號分隔,值用雙引號括起來。鍵值對之間使用一個空格分隔。 注意事項: 為結構體編寫Tag時,必須嚴格遵守鍵值對的規則。結構體標簽的解析代碼的容錯能力很差,一旦格式寫錯,編譯和運行時都不會提示任何錯誤,通過反射也無法正確取值。例如不要在key和value之間添加空格。
例如我們為Student結構體的每個字段定義json序列化時使用的Tag:
GO是編譯性語言,所以函數的順序是無關緊要的,為了方便閱讀,建議入口函數 main 寫在最前面,其余函數按照功能需要進行排列
GO的函數 不支持嵌套,重載和默認參數
GO的函數 支持 無需聲明變量,可變長度,多返回值,匿名,閉包等
GO的函數用 func 來聲明,且左大括號 { 不能另起一行
一個簡單的示例:
輸出為:
參數:可以傳0個或多個值來供自己用
返回:通過用 return 來進行返回
輸出為:
上面就是一個典型的多參數傳遞與多返回值
對例子的說明:
按值傳遞:是對某個變量進行復制,不能更改原變量的值
引用傳遞:相當于按指針傳遞,可以同時改變原來的值,并且消耗的內存會更少,只有4或8個字節的消耗
在上例中,返回值 (d int, e int, f int) { 是進行了命名,如果不想命名可以寫成 (int,int,int){ ,返回的結果都是一樣的,但要注意:
當返回了多個值,我們某些變量不想要,或實際用不到,我們可以使用 _ 來補位,例如上例的返回我們可以寫成 d,_,f := test(a,b,c) ,我們不想要中間的返回值,可以以這種形式來舍棄掉
在參數后面以 變量 ... type 這種形式的,我們就要以判斷出這是一個可變長度的參數
輸出為:
在上例中, strs ...string 中, strs 的實際值是b,c,d,e,這就是一個最簡單的傳遞可變長度的參數的例子,更多一些演變的形式,都非常類似
在GO中 defer 關鍵字非常重要,相當于面相對像中的析構函數,也就是在某個函數執行完成后,GO會自動這個;
如果在多層循環中函數里,都定義了 defer ,那么它的執行順序是先進后出;
當某個函數出現嚴重錯誤時, defer 也會被調用
輸出為
這是一個最簡單的測試了,當然還有更復雜的調用,比如調試程序時,判斷是哪個函數出了問題,完全可以根據 defer 打印出來的內容來進行判斷,非常快速,這種留給你們去實現
一個函數在函數體內自己調用自己我們稱之為遞歸函數,在做遞歸調用時,經常會將內存給占滿,這是非常要注意的,常用的比如,快速排序就是用的遞歸調用
本篇重點介紹了GO函數(func)的聲明與使用,下一篇將介紹GO的結構 struct
標題名稱:go語言type的用法 go語言基本類型
標題路徑:http://m.newbst.com/article26/dodhjjg.html
成都網站建設公司_創新互聯,為您提供移動網站建設、網站排名、ChatGPT、網站導航、軟件開發、網站設計公司
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯