一文詳解Golang中的基礎(chǔ)語法
導(dǎo)包
示例:工程結(jié)構(gòu)如下

GOPATH 設(shè)置為工程根目錄(E:\GO_PROJECT)
test1.go:
package package_test
import "fmt"
/*
定義函數(shù)
*/
func Func1() {
fmt.Println("test1 func1")
}
test2.go:
package package_test
import "fmt"
func Func2() {
fmt.Println("test2 func2")
}
testmain.go:
package main
import "dir1/dir2" // 導(dǎo)入的是【目錄名】
func main() {
package_test.Func1() // 調(diào)用的是【包名】
}
運(yùn)行:
// 方式一 go bulid testmain.go // 編譯(生成可執(zhí)行文件) ./ testmain // 運(yùn)行(可執(zhí)行文件) //方式二 go run testmain.go // 編譯+運(yùn)行
導(dǎo)包結(jié)論:
一個 GO 程序中一定要有 main 包和 main 函數(shù),這是 GO 程序執(zhí)行的入口。
編譯器會根據(jù)指定的相對路徑去搜索包然后導(dǎo)入,這個相對路徑是從 GOROOT 或 GOPATH(workspace)下的 src 下開始搜索:
- GOROOT
- 項(xiàng)目 GOPATH
- 全局 GOPATH
GOlang 和 Java 的區(qū)別是,在 GO 中 import 的是目錄,而不是包名;并且 GO 沒有強(qiáng)制要求包名和目錄名需要一致,即包和目錄是兩個不同的概念。
import 導(dǎo)入的是源文件所在的目錄名,而不是定義的包名。
在代碼中引用包內(nèi)的成員時,使用定義的包名而不是目錄名。
在習(xí)慣上將包名和目錄名保證一致,但這并不是強(qiáng)制規(guī)定。
在同一級目錄中,所有源文件只能使用相同的包名。
同一包名下的變量名、函數(shù)名等不能重復(fù)。
多個目錄下的相同包名,彼此無關(guān)。
包中的成員(如函數(shù))以名稱?字母??寫,決定其訪問權(quán)限:
- ?字母?寫,可被包外訪問(即
public) - ?字母?寫,僅包內(nèi)成員可以訪問(即
private)
工程管理
為了更好的管理項(xiàng)目中的文件,GO 要求將文件都要放在相應(yīng)的目錄中,具體規(guī)定了以下目錄:
src 目錄:以代碼包的形式組織并保存 GO 源碼文件(比如 .go 文件、.c 文件、.h 文件、.s 文件等)pkg 目錄:用于存放經(jīng)由 go install 命令構(gòu)建安裝后的代碼包(包含 GO 庫源碼文件)的 ".a" 歸檔文件。bin 目錄:與 pkg 目錄類似,在通過 go install 命令完成安裝后,保存由 GO 命令源碼文件生成的可執(zhí)行文件。
以上目錄稱為工作區(qū)(Workspace),工作區(qū)其實(shí)就是一個對應(yīng)于特定工程的目錄。
src 目錄用于包含所有的源代碼,是 GO 命令行工具一個強(qiáng)制的規(guī)則;而 pkg 和 bin 則無需手動創(chuàng)建,GO 命令行工具在構(gòu)建過程中會自動創(chuàng)建這些目錄。
變量
變量聲明
- 變量名必須以字母或下劃線開頭,后面可以跟任意數(shù)量的字母、數(shù)字或下劃線。
- 變量的三種聲明&初始化方式如下:
// 方式一:先聲明(有默認(rèn)值),后賦值 var a int a = 10 var b, c string b = "b" c = "c" // 方式二:聲明+賦值 var a int = 10 // 方式三:自動推導(dǎo)類型(注意:這種方式只能在函數(shù)內(nèi)使用) a := 10 b, c := 11, 12 b, c = c, b // 值交換 // 匿名變量 _, i, _, j = 1, 2, 3, 4
格式化輸出
| 格式 | 含義 |
|---|---|
| %% | 一個 % 字面量 |
| %b | 一個二進(jìn)制整數(shù)值(基數(shù)為 2),或者是一個(高級的)用科學(xué)計數(shù)法表示的指數(shù)為 2 的浮點(diǎn)數(shù) |
| %c | 字符型??梢园演斎氲臄?shù)字按照 ASCII 碼相應(yīng)轉(zhuǎn)換為對應(yīng)的字符 |
| %d | 一個十進(jìn)制數(shù)值(基數(shù)為 10) |
| %f | 以標(biāo)準(zhǔn)記數(shù)法表示的浮點(diǎn)數(shù)或者復(fù)數(shù)值 |
| %o | 一個以八進(jìn)制表示的數(shù)字(基數(shù)為8) |
| %p | 以十六進(jìn)制(基數(shù)為 16)表示的一個值的地址,前綴為 0x,字母使用小寫的 a-f 表示 |
| %q | 使用 GO 語法以及必須時使用轉(zhuǎn)義,以雙引號括起來的字符串或者字節(jié)切片 []byte,或者是以單引號括起來的數(shù)字 |
| %s | 字符串。輸出字符串中的字符直至字符串中的空字符(字符串以 '\0' 結(jié)尾,這個 '\0' 即空字符) |
| %t | 以 true 或者 false 輸出的布爾值 |
| %T | 使用 GO 語法輸出的值的類型 |
| %x | 以十六進(jìn)制表示的整型值(基數(shù)為十六),數(shù)字 a-f 使用小寫表示 |
| %X | 以十六進(jìn)制表示的整型值(基數(shù)為十六),數(shù)字 A-F 使用小寫表示 |
基本數(shù)據(jù)類型
| 類型 | 名稱 | 長度 | 零值(默認(rèn)值) | 說明 |
|---|---|---|---|---|
| bool | 布爾類型 | 1 | false | 其值不為真即為假,不可以用數(shù)字代表 true 或 false |
| byte | 字節(jié)型 | 1 | 0 | uint8 的別名 |
| int, uint | 整型 | - | 0 | 有符號 32 位或無符號 64 位 |
| int8 | 整型 | 1 | 0 | -128 ~ 127 |
| uint8 | 整型 | 1 | 0 | 0 ~ 255 |
| int16 | 整型 | 2 | 0 | -32768 ~ 32767 |
| uint16 | 整型 | 2 | 0 | 0 ~ 65535 |
| int32 | 整型 | 4 | 0 | -2147483648 到 2147483647 |
| rune | 整型 | 4 | 0 | int32 的別名 |
| uint32 | 整型 | 4 | 0 | 0 到 4294967295(42 億) |
| int64 | 整型 | 8 | 0 | -9223372036854775808到 92233720368547758070 |
| uint64 | 整型 | 8 | 0 | 到 18446744073709551615(1844 京) |
| float32 | 浮點(diǎn)型 | 4 | 0.0 | 小數(shù)位精確到 7 位 |
| float64 | 浮點(diǎn)型 | 8 | 0.0 | 小數(shù)位精確到 15 位 |
| string | 字符串 | - | "" | utf-8 字符串 |
值的字面量(literal)是指代碼中值的文字表示。一個值可能存在多種字面量表示。
表示基本類型值的文本稱為基本字面量。基本字面量也被稱為字面量常量或未命名常量。
示例:
func main() {
var ch byte = 97 // 聲明字符類型
fmt.Printf("ch=%c", ch) // 輸出 a
}
這里定義了 ch 是一個字符類型,賦值卻是一個整數(shù) 97,打印的結(jié)果是小寫字符 'a'。
原因是:計算機(jī)不能直接存儲字符類型,只能轉(zhuǎn)成數(shù)字存儲,那為什么小寫字符 'a' 對應(yīng)的整數(shù)是 97 呢?因?yàn)橛嬎銠C(jī)是根據(jù) ASCII 碼來存儲的。

強(qiáng)制類型轉(zhuǎn)換
package main
import "fmt"
func main() {
chinese := 97
math := 99
english := 96
fmt.Printf("總分是 %d,平均分(整數(shù))是 %d, 平均分(浮點(diǎn)數(shù))是 %f", chinese+math+english, (chinese+math+english)/3, float32(chinese+math+english)/3)
// 總分是 292,平均分(整數(shù))是 97, 平均分(浮點(diǎn)數(shù))是 97.333336
}
注意:
GO 語言中不允許隱式轉(zhuǎn)換,所有類型轉(zhuǎn)換必須顯式聲明(強(qiáng)制轉(zhuǎn)換),而且轉(zhuǎn)換只能發(fā)生在兩種相互兼容的類型之間
var ch byte = 'c'
// var a int = ch // cannot use ch (type byte) as type int in assignment
var b int = int(ch) // 數(shù)據(jù)類型名(待轉(zhuǎn)換的值)
- int 轉(zhuǎn) float 強(qiáng)制轉(zhuǎn)換:多小數(shù)
- float 轉(zhuǎn) int 強(qiáng)制轉(zhuǎn)換:丟精度
接收鍵盤輸入
package main
import fmt
func main() {
var age int
fmt.Println("請輸入年齡:")
fmt.Scanf("%d", &age) // 將接收的值賦給age變量
fmt.Printf("age=%d", age)
}
常量
常量聲明
func main() {
// 變量:程序運(yùn)行期間,值可以改變,聲明使用var
// 常量:程序運(yùn)行期間,值不可以改變,聲明使用const
const a int = 11
// a = 12 // error:常量不可以修改
const b = 12 // 自動推導(dǎo)類型(常量不可以使用:=)
}
iota 枚舉
iota 常量生成器:用于生成一組遞增的整型常量,減去了每行都要寫一遍初始化表達(dá)式的繁瑣。
func main() {
// 在一個 const 聲明語句中,在第一個聲明的常量所在的行,iota 將會被置為 0,然后在每一個有常量聲明的行遞增 1
const (
a = iota // 0
b = iota // 1
c = iota // 2
)
const d = iota // iota 遇到const,會被置為 0
// 可以只寫一個iota
const (
e = iota // 0
f // 1
g
)
// 同一行值一樣
const (
h = iota // 0
i, j, k = iota, iota, iota // 1
l = iota // 2
)
}
運(yùn)算符
算術(shù)運(yùn)算符
| 運(yùn)算符 | 術(shù)語 |
|---|---|
| + | 加(既可以完成兩個數(shù)字相加,又可以連接兩個字符串) |
| - | 減 |
| * | 乘 |
| / | 除 |
| % | 取模(取余) |
| ++ | 后自增(GO 語言中沒有前自增) |
| -- | 后自減(GO 語言中沒有前自減) |
賦值運(yùn)算符
| 運(yùn)算符 | 說明 | 示例 |
|---|---|---|
| = | 普通賦值 | c = a + b 將 a + b 表達(dá)式結(jié)果賦值給 c |
| += | 相加后再賦值 | c += a 等價于 c = c + a |
| -= | 相減后再賦值 | c -= a 等價于 c = c - a |
| *= | 相乘后再賦值 | c *= a 等價于 c = c * a |
| /= | 相除后再賦值 | c /= a 等價于 c = c / a |
| %= | 求余后再賦值 | c %= a 等價于 c = c % a |
關(guān)系運(yùn)算符
| 運(yùn)算符 | 術(shù)語 | 示例 | 結(jié)果 |
|---|---|---|---|
| == | 相等于 | 4 == 3 | false |
| != | 不等于 | 4 != 3 | true |
| < | 小于 | 4 < 3 | false |
| > | 大于 | 4 > 3 | true |
| <= | 小于等于 | 4 <= 3 | false |
| >= | 大于等于 | 4 >= 1 | true |
邏輯運(yùn)算符
| 運(yùn)算符 | 術(shù)語 | 示例 | 結(jié)果 |
|---|---|---|---|
| ! | 非 | !a | 如果 a 為假,則 !a 為真 如果 a 為真,則 !a 為假 |
| && | 與 | a && b | 如果 a 和 b 都為真,則結(jié)果為真,否則為假 |
| || | 或 | a || b | 如果 a 和 b 有一個為真,則結(jié)果為真,二者都為假時,結(jié)果為假 |
條件語句
if 語句
package main
import "fmt"
func main() {
var score int
fmt.Println("請輸入成績:")
fmt.Scanf("%d", &score)
// if 語句支持一個初始化語句+判斷條件
if good_score := 90; score >= good_score {
fmt.Println("優(yōu)秀")
} else if soso_score := 60; score >= soso_score {
fmt.Println("及格")
} else {
fmt.Println("需要努力")
}
}
switch 語句
注意:case 后面默認(rèn)自帶 break,如果想執(zhí)行完成某個 case 后繼續(xù)執(zhí)行后面的 case,可以使用 fallthrough 關(guān)鍵字。
func main() {
bonus := 5000
var score string
finish := true
fmt.Println("請輸入年終評級:")
switch fmt.Scanf("%s", &score); score {
case "A":
bonus += 1000
case "B":
bonus += 5000
case "C":
case "D":
bonus -= 1000
default:
finish = false
fmt.Println("輸入有誤,請輸入正確的評級")
}
if finish {
fmt.Printf("您的年終獎為:%d", bonus)
}
}
循環(huán)語句
GO 中的 3 種循環(huán)方式:
package main
import "fmt"
func main() {
// 第1種方式
for i := 0; i < 5; i++ {
fmt.Printf("i=%d\n", i)
}
// 第2種方式:類似while循環(huán)
num := 1
for num < 5 {
fmt.Printf("num=%d\n", num)
num++
}
// 第3種方式
for {
fmt.Println("死循環(huán)")
}
}
函數(shù)
函數(shù)定義
函數(shù)就是將一堆代碼進(jìn)行封裝,以便重用的一種機(jī)制。
func 函數(shù)名(){
函數(shù)體
}
參數(shù)列表
import "fmt"
func MyFunc(a int, b int, args ...int) { // 注意:不定長參數(shù)必須放在參數(shù)列表最后
fmt.Println("定長參數(shù)為:", a, b)
for i, data := range args { // 若不需要編號,則可使用 for _, data := range args
fmt.Println("編號為:", i)
fmt.Println("數(shù)據(jù)為:", data)
}
}
func main() {
MyFunc(1, 2, 3, 4, 5)
}
打印結(jié)果:
定長參數(shù)為: 1 2
編號為: 0
數(shù)據(jù)為: 3
編號為: 1
數(shù)據(jù)為: 4
編號為: 2
數(shù)據(jù)為: 5
函數(shù)返回值
// 定義返回值類型
func Add(a int, b int) int {
return a + b
}
// 給返回值命名
func Sub(a int, b int) (sub int) {
sub = a - b
return sub // 也可以只寫 return
}
// 返回多個值
func Sub(a, b, c int) {
a, b, c = 1, 2, 3
return a, b, c // 也可以只寫 return
}
函數(shù)類型
在 GO 語言中還有另外一種定義使用函數(shù)的方式,就是函數(shù)類型。
所謂的函數(shù)類型,就是將函數(shù)作為一種類型可以用來定義變量,基本使用如下:
func Test(a, b int) int {
return a + b
}
// 定義函數(shù)類型:即需要傳遞兩個整型參數(shù),有一個整型返回值的函數(shù)類型
type FuncType func(a int, b int) int // type關(guān)鍵字后面跟著類型的名字(FunType)
func main() {
var result FuncType // 類型是FuncType類型,即函數(shù)類型
result = Test
s := result(1, 2)
fmt.Printf("s=%d", s)
}
匿名函數(shù)
所謂匿名函數(shù)就是沒有名字的函數(shù)。匿名函數(shù)最主要的功能就是實(shí)現(xiàn)了閉包。
package main
import "fmt"
func main() {
num := 9
// 使用方式一:定義匿名函數(shù)并賦值給變量
f1 := func() {
// 在匿名函數(shù)中可以直接訪問main()中定義的局部變量
// 并且在匿名函數(shù)中對變量的值進(jìn)行了修改,最終會影響到整個main()函數(shù)中定義的變量值
num++
fmt.Println("匿名函數(shù):", num)
}
f1() // 10
fmt.Println("main函數(shù):", num) // 10
// 使用方式二:通過函數(shù)類型
type FuncType func() // 沒有參數(shù),沒有返回值
var f2 FuncType = f1
f2()
// 使用方式三:直接調(diào)用
func(a, b int) {
fmt.Println("a + b =", a+b)
}(3, 6)
// 有參有返回值的匿名函數(shù)
min, max := func(a, b int) (min, max int) {
if a > b {
return b, a
} else {
return a, b
}
}(12, 13)
fmt.Printf("min=%d, max=%d\n", min, max)
}
遞歸函數(shù)
示例:階乘
func Test(num int) int {
if num == 1 {
return 1
}
return num * Test(num-1)
}
func main() {
var num int
fmt.Println("請輸入需要階乘的數(shù):")
fmt.Scanf("%d", &num)
fmt.Printf("%d的階乘結(jié)果為:%d", num, Test(num))
}
以上就是一文詳解Golang中的基礎(chǔ)語法的詳細(xì)內(nèi)容,更多關(guān)于Golang基礎(chǔ)語法的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
淺析go中的map數(shù)據(jù)結(jié)構(gòu)字典
golang中的map是一種數(shù)據(jù)類型,將鍵與值綁定到一起,底層是用哈希表實(shí)現(xiàn)的,可以快速的通過鍵找到對應(yīng)的值。這篇文章主要介紹了go中的數(shù)據(jù)結(jié)構(gòu)字典-map,需要的朋友可以參考下2019-11-11
Golang中Set類型的實(shí)現(xiàn)方法示例詳解
這篇文章主要給大家介紹了關(guān)于Golang中Set類型實(shí)現(xiàn)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2017-09-09

