寫在前面
? ? ? ?本文是Go語言的快速入門教程,適合于具有一定C語言或者Java語言基礎(chǔ)的開發(fā)人員,如果您是一位Go語言的熟練使用者,請繞行!像作者這個年紀(jì)的老碼農(nóng)通常都是從Pascal語言或者c語言開始學(xué)習(xí)計算機技術(shù)的,所以學(xué)起Go語言生來就有一種似曾相識的感覺,還是蠻輕松的!
? ? ? ?當(dāng)然,目前筆者也只能算是了解Go語言而已,還不能算熟悉,離精通那就差的更遠(yuǎn)了!說到這個計算機相關(guān)技術(shù)的掌握程度,又得發(fā)點牢騷,了解,熟悉,精通,這是不同的水平層次的表現(xiàn)。作為一個保守的,略帶謙虛氣質(zhì)的老碼農(nóng),我從來不敢說自己精通某某技術(shù),某某語言,頂多敢在簡歷里面寫上熟練掌握和使用某某語言、技術(shù)而已。如若讓我看到誰的簡歷里面敢寫精通某某語言、某某技術(shù),碰巧又遇到我來面試,那他肯定死的很慘。我會面的他無地自容、信心喪失、立馬尋死!當(dāng)然大神除外,大神級的人物也輪不到我來面試,呵呵!
一、Go語言簡介
? ? ? ?咱們書歸正傳,來一起學(xué)習(xí)一下Go語言。Go的全稱是GoLang,“夠浪”你就來學(xué)Go語言,呵呵!筆者之前沒有Go語言的任何經(jīng)驗,也是臨危受命,被逼無奈,開始了“夠浪”的學(xué)習(xí)和開發(fā)歷程。

? ? ? ?這個小地鼠不一般,它是Go語言的吉祥物,蠻可愛的!就和Go一樣,簡潔明了。
? ? ? ?Go是一個開源的編程語言,它能夠構(gòu)造簡單、可靠且高效的軟件。Go是從2007年末由Google公司的Robert Griesemer, Rob Pike, Ken Thompson主持開發(fā)的,并最終于2009年11月開源,在2012年早些時候發(fā)布了Go 1穩(wěn)定版本?,F(xiàn)在Go的開發(fā)已經(jīng)是完全開放的,并且擁有一個活躍的社區(qū)。
Go語言有如下特點:
- 簡潔、快速、安全
- 并行、有趣、開源
- 內(nèi)存管理、數(shù)組安全、編譯迅速
? ? ? ?下面我們就一起來開啟“夠浪”的快速學(xué)習(xí)之旅。
二、Go語言基礎(chǔ)
? ? ? ?計算機軟件經(jīng)歷了數(shù)十年的發(fā)展,形成了多種學(xué)術(shù)流派,有面向過程編程、面向?qū)ο缶幊獭⒑瘮?shù)式編程、面向消息編程等,這些思想究竟孰優(yōu)孰劣,眾說紛紜,作者不予評價。
? ? ? ?Go語言對這些思想均有所吸收。例如,Go語言接受了函數(shù)式編程的一些想法,支持匿名函數(shù)與閉包。再如,Go語言接受了以Erlang語言為代表的面向消息編程思想,支持goroutine和通道,并推薦使用消息而不是共享內(nèi)存來進(jìn)行并發(fā)編程。總體來說,Go語言是一個非?,F(xiàn)代化的語言,精小但非常強大。
? ? ? ?Go語言是谷歌2009發(fā)布的第二款開源編程語言。Go語言專門針對多處理器系統(tǒng)應(yīng)用程序的編程進(jìn)行了優(yōu)化,使用Go編譯的程序可以媲美C或C++代碼的速度,而且更加安全、支持并行進(jìn)程。
Go 語言的主要特性如下:
- 自動垃圾回收
- 更豐富的內(nèi)置類型
- 函數(shù)多返回值
- 錯誤處理
- 匿名函數(shù)和閉包
- 類型和接口
- 并發(fā)編程
- 反射
- 語言交互性
? ? ? ?說了這么多,趕緊讓大家來親身體會一下吧!因為Go語言在語法上很大程度的類似C語言,故此本文不會面面俱到的講解Go的語法,只會著重指出與C不同的地方以及Go自身有特色的內(nèi)容。
? ? ? ?第一個Go程序,仍然從hello world開始!
package main
import "fmt"
func main() {
fmt.Println("Hello, World!")
}
? ? ? ?也像Java也像C,有package來做包管理,import來導(dǎo)入類庫(包),main是入口函數(shù)。
- 第一行代碼 package main 定義了包名。package main表示一個可獨立執(zhí)行的程序,每個Go應(yīng)用程序都包含一個名為main的包;
- import "fmt" 告訴Go編譯器這個程序需要使用fmt包;
- func main() 是程序開始執(zhí)行的函數(shù),即入口函數(shù);
- 當(dāng)標(biāo)識符(包括常量、變量、類型、函數(shù)名、結(jié)構(gòu)字段等)以一個大寫字母開頭,那么使用這種形式的標(biāo)識符對象就可以被外部包的代碼所使用,這被稱為導(dǎo)出(類似OOP中的public);標(biāo)識符如果以小寫字母開頭,則對包外是不可見的,但是他們在整個包的內(nèi)部是可見并且可用的(類似于OOP中的protected )。
? ? ? ?在Go程序中,一行代表一個語句結(jié)束。每個語句不需要以分號;結(jié)尾,因為這些工作都將由Go編譯器自動完成。如果你打算將多個語句寫在同一行,它們則必須使用;人為區(qū)分,但在實際開發(fā)中并不鼓勵這種做法。
? ? ? ?下面就從Go的語法方面介紹Go的特點,主要集中在區(qū)別于C語言的部分。
標(biāo)識符
? ? ? ?Go語言標(biāo)識符、關(guān)鍵字、保留字、注釋與C語言類似,不再贅述。
變量聲明
? ? ? ?Go使用var來聲明變量,變量類型放在后面,例如:
var age int
一次可以聲明多個變量,例如:
var a, b int = 1, 2
? ? ? ?聲明變量可以省略var,使用:=聲明符(初始化聲明)。但要注意省略 var, := 左側(cè)如果沒有聲明新的變量,就產(chǎn)生編譯錯誤。例如:
var intValue int
intValue := 1 //這時候會產(chǎn)生編譯錯誤
intValue, intValue1 := 1, 2 //此時不會產(chǎn)生編譯錯誤,因為有新的變量聲明, := 是一個聲明語句
可以將
var f string = "test"
簡寫為
f := "test"
? ? ? ?因為Go可以根據(jù)值自行判定變量類型,可以在變量初始化時省略變量的類型而由系統(tǒng)自動推斷。
指針
? ? ? ?與c語言類似,Go也使用指針,&符號返回變量的地址,*符號聲明指針變量。
條件判斷語句
? ? ? ?Go的條件判斷語句同樣有if else和switch,if語句沒有什么特別之處,switch語句倒是有很大不同。
? ? ? ?Go 編程語言中 if 語句的語法如下:
if 布爾表達(dá)式 {
}
if 布爾表達(dá)式 {
} else {
}
? ? ? ?Go 編程語言中 switch 語句的語法如下:
switch var1 {
case val1:
...
case val2:
...
default:
...
}
? ? ? ?變量var1可以是任何類型,而val1和val2則可以是同類型的任意值。類型不被局限于常量或整數(shù),但必須是相同的類型;或者最終結(jié)果為相同類型的表達(dá)式。也可以同時測試多個可能符合條件的值,使用逗號分割。不同的case之間不需要使用break分隔。
? ? ? ?switch語句還有一個fallthrough特性。使用fallthrough會強制執(zhí)行后面的一條case語句,fallthrough不會判斷下一條 case的表達(dá)式結(jié)果是否為true,直接執(zhí)行。
? ? ? ?Go語言還有一個特殊的控制結(jié)構(gòu),select語句,與switch語句有些類似。每個case 必須是一個通信操作,要么是發(fā)送要么是接收。select會隨機執(zhí)行一個可運行的case。如果沒有case可運行,它將阻塞,直到有case可運行。
? ? ? ?Go 編程語言中 select 語句的語法如下:
select {
case 通信操作 :
執(zhí)行語句;
case 通信操作 :
執(zhí)行語句;
...
default :
執(zhí)行語句;
}
Range
? ? ? ?在講循環(huán)語句之前先說一下Range關(guān)鍵字。Go語言中range關(guān)鍵字用于for循環(huán)中迭代數(shù)組(array)、切片(slice)、通道(channel)或集合(map)的元素。在數(shù)組和切片中它返回元素的索引和索引對應(yīng)的值,在集合中返回key-value對的key值。
循環(huán)語句
? ? ? ?Go 語言沒有while和do...while語法,可以通過for 循環(huán)來實現(xiàn)其使用效果。Go語言的For循環(huán)有3種形式:
- 和 C 語言的 for 一樣:for init; condition; post { }
- 和 C 語言的 while 一樣:for condition { }
- 和 C 語言的 for(;;) 一樣:for { }
? ? ? ?循環(huán)控制語句有break, continue, goto。goto語句通常與條件語句配合使用??捎脕韺崿F(xiàn)條件轉(zhuǎn)移,構(gòu)成循環(huán),跳出循環(huán)體等功能。但是,在結(jié)構(gòu)化程序設(shè)計中一般不主張使用goto語句, 以免造成程序流程的混亂,使理解和調(diào)試程序都產(chǎn)生困難。
? ? ? ?for循環(huán)的range格式可以對slice、map、數(shù)組、字符串等進(jìn)行迭代循環(huán)。
for key, value := range aMap {
newMap[key] = value
}
Go的函數(shù)
? ? ? ?Go語言函數(shù)定義格式如下:
func function_name( [parameter list] ) [return_types] {
函數(shù)體
}
? ? ? ?Go函數(shù)可以有多個返回值,這是Go的一大特點。如下例所示:
package main
import "fmt"
func swap(x, y string) (string, string) {
return y, x
}
func main() {
a, b := swap("Google", "Runoob")
fmt.Println(a, b)
}
? ? ? ?Go與C一樣,參數(shù)傳遞方式有值傳遞和引用傳遞。默認(rèn)情況下,Go語言使用的是值傳遞,即在調(diào)用過程中不會影響到實際參數(shù)。
? ? ? ?Go的函數(shù)定義后可作為另外一個函數(shù)的實參數(shù)傳入,Go語言可以很靈活的創(chuàng)建函數(shù),并作為另外一個函數(shù)的實參。函數(shù)作為參數(shù)傳遞,實現(xiàn)回調(diào),如下例所示:
package main
import "fmt"
// 聲明一個函數(shù)類型
type cb func(int) int
func main() {
testCallBack(1, callBack)
testCallBack(2, func(x int) int {
fmt.Printf("call back,x:%d\n", x)
return x
})
}
func testCallBack(x int, f cb) {
f(x)
}
func callBack(x int) int {
fmt.Printf("call back,x:%d\n", x)
return x
}
? ? ? ?Go語言支持匿名函數(shù),可作為閉包。匿名函數(shù)是一個"內(nèi)聯(lián)"語句或表達(dá)式。匿名函數(shù)的優(yōu)越性在于可以直接使用函數(shù)內(nèi)的變量,不必聲明。
? ? ? ?Go語言中同時有函數(shù)和方法。一個方法就是一個包含了接受者的函數(shù),接受者可以是命名類型或者結(jié)構(gòu)體類型的一個值或者是一個指針。所有給定類型的方法屬于該類型的方法集。語法格式如下:
func (variable_name variable_data_type) function_name() [return_type] {
/* 方法體 */
}
變量作用域
? ? ? ?Go 語言中變量可以在三個地方聲明:
- 函數(shù)內(nèi)定義的變量稱為局部變量;
- 在函數(shù)體外聲明的變量稱之為全局變量,全局變量可以在整個包甚至外部包(被導(dǎo)出后)使用;
- 函數(shù)定義中的變量稱為形式參數(shù);
? ? ? ?Go 語言程序中全局變量與局部變量名稱可以相同,但是函數(shù)內(nèi)的局部變量會被優(yōu)先考慮。
數(shù)組
? ? ? ?Go語言數(shù)組聲明需要指定元素類型及元素個數(shù),語法格式如下:
var variable_name [SIZE] variable_type
初始化數(shù)組:
var balance = [6]float32{100.0, 2.1, 3.4, 7.6, 30.2, 8.9}
切片
? ? ? ?Go語言切片實際上就是動態(tài)數(shù)組。與數(shù)組相比切片的長度是不固定的,可以追加元素,在追加時可能使切片的容量增大。
? ? ? ?你可以聲明一個未指定大小的數(shù)組來定義切片:
var sliceA []type
切片不需要說明長度?;蚴褂胢ake()函數(shù)來創(chuàng)建切片。也可以指定容量,其中capacity為可選參數(shù)。
make([]T, length, capacity)
切片提供了計算容量的方法cap()可以測量切片最長可以達(dá)到多少。一個切片在未初始化之前默認(rèn)為nil,長度為0。
空值
? ? ? ?Go語言的空值為nil,在概念上和其它語言的null、None、NULL一樣。
結(jié)構(gòu)體
? ? ? ?Go語言的結(jié)構(gòu)體與C語言類似,結(jié)構(gòu)體定義需要使用 type 和 struct 語句。struct 語句定義一個新的數(shù)據(jù)類型,結(jié)構(gòu)體有中有一個或多個成員。type 語句設(shè)定了結(jié)構(gòu)體的名稱。結(jié)構(gòu)體的格式如下:
type struct_variable_type struct {
member definition;
member definition;
...
member definition;
}
? ? ? ?如果要訪問結(jié)構(gòu)體成員,需要使用點號"."操作符,使用結(jié)構(gòu)體指針訪問結(jié)構(gòu)體成員,同樣使用 "." 操作符。
Map
? ? ? ?Key/value的鍵值對,可以使用內(nèi)建函數(shù) make ,也可以使用map關(guān)鍵字來定義Map:
/* 聲明變量,默認(rèn) map 是 nil */
var map_variable map[key_data_type]value_data_type
/* 使用 make 函數(shù) */
map_variable := make(map[key_data_type]value_data_type)
類型轉(zhuǎn)換
? ? ? ?類型轉(zhuǎn)換用于將一種數(shù)據(jù)類型的變量轉(zhuǎn)換為另外一種類型的變量。Go語言類型轉(zhuǎn)換基本格式如下:
type_name(expression)
type_name為類型,expression為表達(dá)式。
Interface
? ? ? ?Go語言提供了另外一種數(shù)據(jù)類型即接口,它把所有的具有共性的方法定義在一起,任何其他類型只要實現(xiàn)了這些方法就是實現(xiàn)了這個接口。
type interface_name interface {
method1 [return_type]
method2 [return_type]
method3 [return_type]
...
methodN [return_type]
}
錯誤處理
? ? ? ?Go語言通過內(nèi)置的錯誤接口提供了非常簡單的錯誤處理機制。error類型是一個接口類型,這是它的定義:
type error interface {
Error() string
}
? ? ? ?我們可以在編碼中通過實現(xiàn)error接口類型來生成錯誤信息。函數(shù)通常在最后的返回值中返回錯誤信息,使用errors.New 可返回一個錯誤信息。
? ? ? ?此外,panic與recover是Go的兩個內(nèi)置函數(shù),這兩個內(nèi)置函數(shù)用于處理Go運行時的錯誤,panic用于主動拋出錯誤,recover用來捕獲panic拋出的錯誤。還有一個defer語句,其目的類似于Java的finally,在當(dāng)前函數(shù)的末尾執(zhí)行一些清理代碼,而不管此函數(shù)如何退出。defer的有趣之處在于它跟代碼塊沒有聯(lián)系,可以隨時出現(xiàn)。
并發(fā)
? ? ? ?Go語言支持并發(fā),我們只需要通過go關(guān)鍵字來開啟goroutine即可。goroutine是輕量級線程,goroutine的調(diào)度是由Golang運行時進(jìn)行管理的。goroutine語法格式:
go 函數(shù)名( 參數(shù)列表 )
? ? ? ?同一個程序中的所有g(shù)oroutine共享同一個地址空間。goroutine是golang中在語言級別實現(xiàn)的輕量級線程,僅僅利用go就能立刻起一個新線程。
通道
? ? ? ?通道(channel)是用來傳遞數(shù)據(jù)的一個數(shù)據(jù)結(jié)構(gòu)。通道可用于兩個goroutine之間通過傳遞一個指定類型的值來同步運行和通訊。操作符<- 用于指定通道的方向,發(fā)送或接收。如果未指定方向,則為雙向通道。
ch <- v // 把v發(fā)送到通道ch
v := <-ch // 從ch接收數(shù)據(jù), 并把值賦給v
? ? ? ?聲明一個通道很簡單,我們使用chan關(guān)鍵字即可,通道在使用前必須先創(chuàng)建。
ch := make(chan int)
三、Web框架
? ? ? ?互聯(lián)網(wǎng)時代就得學(xué)習(xí)一下Web框架。Gin是一個go寫的web框架,具有高性能的優(yōu)點。官方地址:https://github.com/gin-gonic/gin。
1、下載并安裝
$ go get -u github.com/gin-gonic/gin
2、在代碼中導(dǎo)入它
import "github.com/gin-gonic/gin"
使用gin需要Go的版本號為1.6或更高。
? ? ? ?下面我們就通過一個簡單的例子來快速入門Gin。
package main
import "github.com/gin-gonic/gin"
func main() {
router := gin.Default()
router.GET("/ping", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "pong",
})
})
router.Run() // listening on 0.0.0.0:8080
}
運行這段代碼并在瀏覽器中訪問 http://localhost:8080。
HTTP方法
? ? ? ?可以使用 GET, POST, PUT, PATCH, DELETE, OPTIONS等方法。
參數(shù)獲取
獲取路徑中的參數(shù):
router.GET("/user/:name", func(c *gin.Context) {
name := c.Param("name")
c.String(http.StatusOK, "Hello %s", name)
})
獲取Get參數(shù):
firstname := c.DefaultQuery("firstname", "Guest")
lastname := c.Query("lastname")
獲取Post參數(shù):
message := c.PostForm("message")
nick := c.DefaultPostForm("nick", "anonymous")
路由分組
使用Group方法進(jìn)行路由分組:
v1 := router.Group("/v1")
v2 := router.Group("/v2")
使用中間件
可以使用在全局上,也可以使用在分組上。
模型綁定和驗證
? ? ? ?若要將請求主體綁定到結(jié)構(gòu)體中,請使用模型綁定,目前支持JSON、XML、YAML和標(biāo)準(zhǔn)表單值(foo=bar&boo=baz)的綁定。需要在綁定的字段上設(shè)置tag,比如,綁定格式為json,需要這樣設(shè)置 json:"fieldname" 。當(dāng)我們使用綁定方法時,Gin會根據(jù)Content-Type推斷出使用哪種綁定器,如果你確定你綁定的是什么,你可以使用MustBindWith或者BindingWith。下面以綁定JSON類型為例:
// 綁定為json
type Login struct {
User string `json:"user" binding:"required"`
Password string `json:"password" binding:"required"`
}
func main() {
router := gin.Default()
// Example for binding JSON ({"user": "test", "password": "123"})
router.POST("/login", func(c *gin.Context) {
var json Login
if err := c.ShouldBindJSON(&json); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
if json.User != "test" || json.Password != "123" {
c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"})
return
}
c.JSON(http.StatusOK, gin.H{"status": "Login successfully!"})
})
}
? ? ? ?關(guān)于Gin就講這么多,夠用了,想了解更加詳細(xì)的內(nèi)容,請訪問Gin的官方網(wǎng)站。
四、ORM工具
? ? ? ?有了Web框架,還得有ORM才算配齊。xorm是一個Go語言O(shè)RM庫. 通過它可以使數(shù)據(jù)庫操作非常簡便。xorm的特性如下:
- 支持Struct和數(shù)據(jù)庫表之間的靈活映射,并支持自動同步表結(jié)構(gòu)
- 事務(wù)支持
- 支持原始SQL語句和ORM操作的混合執(zhí)行
- 使用連寫來簡化調(diào)用
- 支持使用Id, In, Where, Limit, Join, Having, Table, Sql, Cols等函數(shù)和結(jié)構(gòu)體等方式作為條件
- 支持級聯(lián)加載Struct
- 支持LRU緩存(支持memory, memcache, leveldb, redis緩存Store) 和 Redis緩存
- 支持反轉(zhuǎn),即根據(jù)數(shù)據(jù)庫自動生成xorm的結(jié)構(gòu)體
- 支持事件
- 支持created, updated, deleted和version記錄版本(即樂觀鎖)
? ? ? ?下面還是通過一個簡單的例子來入門xorm,使用Mysql數(shù)據(jù)庫。
//匿名導(dǎo)入包:只導(dǎo)入包,而不使用任何包內(nèi)的結(jié)構(gòu)和類型,也不調(diào)用包內(nèi)的任何函數(shù)
import _ "github.com/go-sql-driver/mysql"
type Account struct {
Id int64
Name string `xorm:"unique"`
Balance float64
Version int `xorm:"version"`
}
var x *xorm.Engine
x, err := xorm.NewEngine("mysql", "root:123456@/admin?charset=utf8")
獲取數(shù)據(jù)
? ? ? ?查詢單條數(shù)據(jù)使用Get方法,在調(diào)用Get方法時需要傳入一個對應(yīng)結(jié)構(gòu)體的指針,同時結(jié)構(gòu)體中的非空field自動成為查詢的條件和前面的方法條件組合在一起查詢。
根據(jù)Id來獲得單條數(shù)據(jù):
a:=&Account{}
has, err := x.Id(id).Get(a)
根據(jù)where獲取單條數(shù)據(jù):
a := new(Account)
has, err := x.Where("name=?", "admin").Get(a)
返回的結(jié)果為兩個參數(shù),一個has(bool類型)為該條記錄是否存在,第二個參數(shù)err為是否有錯誤。不管err是否為nil,has都有可能為true或者false。
批量獲取數(shù)據(jù)
err = x.Desc("balance").Find(&as)
Find方法的第一個參數(shù)為slice的指針或Map指針,即為查詢后返回的結(jié)果,第二個參數(shù)可選,為查詢的條件struct的指針。
增刪改操作
增加操作:
_, err := x.Insert(&Account{Name: name, Balance: balance})
刪除操作:
_, err := x.Delete(&Account{Id: id})
? ? ? ?方法 Delete 接受參數(shù)后,會自動根據(jù)傳進(jìn)去的值進(jìn)行查找,然后刪除。比如此處,我們指定了 Account 的 ID 字段,那么就會刪除 ID 字段值與我們所賦值相同的記錄;如果您只對 Name 字段賦值,那么 xorm 就會去查找 Name 字段值匹配的記錄。如果多個字段同時賦值,
則是多個條件同時滿足的記錄才會被刪除。
更新操作:
a := &Account{Id:1}
has, err := x.Get(a)
a.Balance += 1
_, err := x.Update(a)
事務(wù)
// 創(chuàng)建 Session 對象
sess := x.NewSession()
defer sess.Close()// 開啟事務(wù)
if err = sess.Begin(); err != nil {
return err
}
if _, err = sess.Update(a1); err != nil { // 發(fā)生錯誤時進(jìn)行回滾
sess.Rollback()
return err
}
// 完成事務(wù)
return sess.Commit()
五、總結(jié)
? ? ? ?實際上筆者也是一名Go的新手,該部分記錄一下筆者在使用Go的過程中的一些經(jīng)驗總結(jié)以及踩過的坑。
- {不能單獨放在一行;
- Go語言的字符串連接可以通過+實現(xiàn);
- 空標(biāo)識符“_”是一個占位符,用于在賦值操作的時候?qū)⒛硞€值賦值給空標(biāo)識符,從而達(dá)到丟棄該值的目的??諛?biāo)識符不是一個新的變量,因此將它用于:=操作符的時候,必須同時為至少另一個值賦值;
- 如果在相同的代碼塊中,我們不可以再次對于相同名稱的變量使用初始化聲明:=,編譯器會提示錯誤 no new variables on left side of :=,但是=賦值是可以的,因為這是給相同的變量賦予一個新的值;
- 如果你在定義變量a之前使用它,則會得到編譯錯誤 undefined: a;
- 如果你聲明了一個局部變量卻沒有在相同的代碼塊中使用它,同樣會得到編譯錯誤:xx declared and not used;
- 單純地給變量(如:a)賦值是不夠的,這個值必須被使用,但是全局變量是允許聲明但不使用的;
- Go沒有三目運算符,所以不支持 ?: 形式的條件判斷;
- int轉(zhuǎn)換為String類型時,不能用String()進(jìn)行類型轉(zhuǎn)換,而應(yīng)該使用 strconv.Itoa();
Package strconv implements conversions to and from string representations of basic data types.
Itoa is equivalent to FormatInt(int64(i), 10)
如果使用string()的話,將返回UTF-8編碼值。
string is the set of all strings of 8-bit bytes, conventionally but not necessarily representing UTF-8-encoded text.
A string may be empty, but not nil. Values of string type are immutable.
六、學(xué)習(xí)資源
- 菜鳥教程 - https://www.runoob.com/go/go-tutorial.html
- Gin框架中文文檔 - http://www.itdecent.cn/p/98965b3ff638/
- golang-xorm庫快速學(xué)習(xí) - https://www.imooc.com/article/46419
? ? ? ?? ? ? ?? ? ? ?? ? ? ?? ? ? ?? ? ? ?? ? ? ?? ? ? ?? ? ? ?? ? ? ?? ? ? ?2019年8月13日 星期二 于青島