運行命令 go run xx.go或者 go build xx.go + ./xx package main import ( "fmt" ) func main() { fmt.Println("hello world") } 基礎語法 package main import ( "fmt" ...
運行命令 go run xx.go
或者 go build xx.go + ./xx
package main
import (
"fmt"
)
func main() {
fmt.Println("hello world")
}
基礎語法
package main
import (
"fmt"
"math"
)
func main() {
var a = "ivanlee"
var b, c int = 1, 2
var d = true
var e float64
f := float32(e)
g := a + "_regina"
fmt.Println(a, b, c, d, e, f)
fmt.Println("g=", g)
const s string = "constant"
const h = 50000000
const i = 3e20 / h
fmt.Println(s, h, i, math.Sin(i))
}
- 定義變數可分為:var+變數定義,變數 :=
- 定義常量時沒有類型限制,其可根據上下文自行進行定義
if/else
func main() {
if 7%2 == 0 {
fmt.Println("7%2==0")
} else {
fmt.Println("7%2!=0")
}
if num := 9; num < 0 {
fmt.Println("num < 0")
} else if num < 10 {
fmt.Println("0<num<10")
} else {
fmt.Println("num>10")
}
}
if 條件當中的語句不需要加括弧,也可以在if當中添加變數的定義
for迴圈
go語言當中只有for迴圈,沒有while迴圈
func main() {
var i int = 1
for {
fmt.Println("loop")
i = i + 1
if i == 3 {
break
}
}
for n := 1; n < 9; n++ {
if n%2 == 0 {
continue
}
fmt.Println("n=",n)
}
for i <= 5 {
fmt.Println("i=", i)
i = i + 1
}
}
如果for迴圈當中沒有條件,則相當於python裡面的while True
,內部沒有break則會一直執行
也可以像C++語法中的正常三個條件值進行編寫,也可以提前定義變數以後進行範圍操作,這一步也類似於while i<=5
。
switch
func main() {
a := 2
switch a {
case 1:
fmt.Println("a=1")
case 2:
fmt.Println("a=2")
case 3, 4, 5:
fmt.Println("a=3 or 4 or 5")
default:
fmt.Println("other")
}
t := time.Now()
switch {
case t.Hour() < 12:
fmt.Println("morning")
default:
fmt.Println("afternoon")
}
}
switch分支語句的用法中可以使用任意類型的變數,也可以在case語句當中使用,並且當case被命中之後,會直接跳出當前switch,運行後面的語句
數組
var a [5]int
a[4] = 100
fmt.Println(a[4], len(a))
b := [5]int{1, 2, 3, 4, 5}
fmt.Println(b)
var c [2][3]int
for i := 0; i < 2; i++ {
for j := 0; j < 3; j++ {
c[i][j] = i + j
}
}
fmt.Println("2d: ", c)
定義數組時,大小必須是固定的,所以數組也並不常用。所以一般使用 切片技術,這樣也就更像python的數組
s := make([]string, 3)
s[0] = "a"
s[1] = "b"
fmt.Println(s)
fmt.Println(len(s))
s = append(s, "c")
s = append(s, "d", "f")
fmt.Println(s)
c := make([]string, len(s))
copy(c, s)
fmt.Println(c)
fmt.Println(c[2:5])
fmt.Println(c[:5])
fmt.Println(c[2:])
good := []string{"g", "o", "o", "d"}
fmt.Println(good)
map
m := make(map[string]int)
m["one"] = 1
m["two"] = 2
fmt.Println(m)
fmt.Println(m["one"])
fmt.Println(m["regina"]) //沒有key時會輸出0
value, ok := m["regina"]
fmt.Println(value, ok)
delete(m, "two")
m2 := map[string]int{"three": 3, "four": 4}
var m3 = map[string]int{"five": 5, "six": 6}
fmt.Println(m2, m3)
make函數就是只用於定義,如果要賦值則直接在後面用{}進行賦值
map更像python裡面的字典,可以用delete函數刪除key,如果map裡面沒有key,則會有一個false值
range
n := []int{1,2,3,4,5}
sum := 0
for i, num := range n {
sum += num
if num == 2 {
fmt.Println("index:", i, " num:", num)
}
}
m := map[string]string{"a": "A", "b": "B"}
for k, v := range m {
fmt.Println("key:", k, " value:", v)
}
for k := range m {
fmt.Println("key:", k)
}
函數
func add(a int, b int) int {
return a + b
}
func add2(a, b int) int {
return a + b
}
func exist(m map[string]string, k string) (v string, ok bool) {
v, ok = m[k]
return v, ok
}
func main() {
fmt.Println(add(1, 2))
fmt.Println(add2(2, 3))
fmt.Println(exist(map[string]string{"a": "A", "b": "B"}, "A"))
fmt.Println(exist(map[string]string{"a": "A", "b": "B"}, "a"))
}
函數定義時,參數需要類型定義,以及返回時的類型。如果有多個函數返回值,則分別說明類型
指針
func add(n int) {
n += 2
}
func add2ptr(n *int) {
*n += 2
}
func main() {
n := 5
add(n)
fmt.Println(n)
add2ptr(&n)
fmt.Println(&n)
fmt.Println(n)
}
結構體
Go 語言中數組可以存儲同一類型的數據,但在結構體中我們可以為不同項定義不同的數據類型。結構體是由一系列具有相同類型或不同類型的數據構成的數據集合。
func checkpwd(u user, pwd string) bool {
if u.password == pwd {
return true
} else {
return false
}
}
func checkpwd2(u *user, pwd string) bool {
if u.password == pwd {
return true
} else {
return false
}
}
func main() {
a := user{name: "ivanlee", password: "regina"}
b := user{"ivanlee", "regina"}
c := user{name: "ivanlee"}
c.password = "regina"
var d user
d.name = "ivanlee"
d.password = "password"
fmt.Println(checkpwd(a, "zjr")) //false
fmt.Println(checkpwd2(&b, "regina")) //true
}
定義一個結構體之後,實例化有abcd四種賦值方法。結構體也擁有其方法,寫法要更加簡潔
type user struct {
name string
password string
}
func (u user) checkpwd(pwd string) bool {
return u.password == pwd
}
func (u *user) resetpwd(pwd string) {
u.password = pwd
}
func main() {
a := user{name: "ivanlee", password: "regina"}
a.resetpwd("zjr")
fmt.Println(a.checkpwd("zjr")) //true
}
func (u user) checkpwd(pwd string) bool` { 這種定義函數的方法,可以使得每一個實例化結構體的對象直接調用,把`func(a,pwd)`的寫法變成了`a.func(pwd)
字元串操作
func main() {
a := "hello"
fmt.Println(strings.Contains(a, "ll"))//包含
fmt.Println(strings.Count(a, "l"))
fmt.Println(strings.HasPrefix(a, "he"))
fmt.Println(strings.HasSuffix(a, "llo"))
fmt.Println(strings.Index(a, "ll"))
fmt.Println(strings.Join([]string{"hel", "lo"}, "-"))
fmt.Println(strings.Repeat(a, 2))
fmt.Println(strings.Split("a-b-c", "-")) //得到一個數組
fmt.Println(strings.ToLower(a))
fmt.Println(strings.ToUpper(a))
fmt.Println(len(a))
}
字元串格式化
p := point{1, 2}
fmt.Printf("%+v\n", p)
fmt.Printf("%#v\n", p)
fmt.Printf("type: %T\n", p)
fmt.Printf("int %d\n", 123)
fmt.Printf("bin %b\n", 14)
fmt.Printf("char %c\n", 33)
fmt.Printf("hex %x\n", 27)
fmt.Printf("float1 %f\n", 78.9)
fmt.Printf("float2: %e\n", 123400000.0)
fmt.Printf("float3: %E\n", 123400000.0)
fmt.Printf("str1 %s\n", "\"string\"")
fmt.Printf("str2: %q\n", "\"string\"")
fmt.Printf("str3: %x\n", "hex this")
fmt.Printf("pointer: %p\n", &p)
fmt.Printf("width1: |%6d|%6d|\n", 12, 345)
fmt.Printf("width2: |%6.2f|%6.3f|\n", 1.2, 3.45)
fmt.Printf("width3: |%-6.2f|%-6.2f|\n", 1.2, 3.45)
fmt.Printf("width4: |%6s|%6s|\n", "foo", "b")
fmt.Printf("width5: |%-6s|%-6s|\n", "foo", "b")
s := fmt.Sprintf("sprintf: a %s", "string")
fmt.Println(s)
fmt.Fprintf(os.Stderr, "io: an %s\n", "error")
第3行:如果值是一個結構體,%+v
的格式化輸出內容將包括結構體的欄位名。
第4行:%#v
根據 Go 語法輸出值,即會產生該值的源碼片段
第5行:需要列印值的類型,使用 %T
第7行:格式化整型數有多種方式,使用 %d
進行標準的十進位格式化。
8-10行:分別是二進位,字元化,16進位
第11行:%f
表示浮點數
12-13行:%e
和 %E
將浮點型格式化為(稍微有一點不同的)科學記數法表示形式。
第15行:%s
表示輸出字元串,如果遇到雙引號,使用%q
第17行:%x
輸出使用 base-16 編碼的字元串, 每個位元組使用 2 個字元表示。
第19行:要輸出一個指針的值,使用 %p
第21行:要指定整數的寬度,請在動詞 “%” 之後使用數字。 預設情況下,結果會右對齊並用空格填充。
第22行:也可以指定浮點型的輸出寬度,同時也可以通過 寬度.精度
的語法來指定輸出的精度。
第23行:要左對齊,使用 - 標誌
第27行:Printf通過 os.Stdout
輸出格式化的字元串。 Sprintf 則格式化並返回一個字元串而沒有任何輸出
第30行:用 Fprintf
來格式化並輸出到 io.Writers
而不是 os.Stdout
json
對於一個已有的結構體,只要保證每個欄位段第一個字母是大寫,也就是公開欄位,那麼這個結構體就可以用JSON.marshaler
去序列化,變成一個json字元串。序列化之後的字元串可以通過JSON.unmarshaler
去反序列化到一個空的變數裡面。
package main
import (
"encoding/json"
"fmt"
)
type user struct {
Name string
Age int
Hobby []string
}
func main() {
a := user{"ivanlee", 18, []string{"basketball", "math"}}
buf, err := json.Marshal(a)
if err != nil {
panic(err)
}
fmt.Println(buf)
fmt.Println(string(buf))
buf, err = json.MarshalIndent(a, "", "\t")
if err != nil {
panic(err)
}
fmt.Println(string(buf))
var b user
err = json.Unmarshal(buf, &b)
if err != nil {
panic(err)
}
fmt.Printf("%#v\n", b)
}
- 只要是可導出成員(變數首字母大寫),都可以轉成json。
時間處理
time.Now
得到的當前時間的時區跟電腦的當前時區一樣。time.Parse
把時間字元串轉換為Time,時區是UTC時區。其中layout的時間必須是 "2006-01-02 15:04:05"****這個時間,不管格式如何,時間點一定得是這個,如:"Jan 2, 2006 at 3:04pm (MST)","2006-Jan-02"等。如換一個時間解析出來的時間就不對了,要特別註意這一點。- 不管Time變數存儲的是什麼時區,其Unix()方法返回的都是距離UTC時間:1970年1月1日0點0分0秒的秒數。
Unix()
返回的秒數可以是負數,如果時間小於1970-01-01 00:00:00的話。
func main() {
now := time.Now()
fmt.Println(now)
t1 := time.Date(2000, 1, 27, 1, 25, 36, 0, time.UTC)
t2 := time.Date(2000, 1, 22, 1, 25, 36, 0, time.UTC)
fmt.Println(t1)
fmt.Println(t1.Year(), t1.Month(), t1.Day())
fmt.Println(t1.Format("2006-01-02 15:04:05"))
diff := t2.Sub(t1)
fmt.Println(diff)
t3, err := time.Parse("2006-01-02 15:04:05", "2022-02-10 01:23:45")
if err != nil {
panic(err)
}
fmt.Println(t3 == t1)
fmt.Println(now.Unix())
}
數字和字元轉換
在go語言中,字元串和數字之間的轉換都存在"STR/conv"
包中,可以使用parseint
或者parseFloat
函數解析一個字元串,可以使用Atoi
函數把一個十進位的字元串轉換成數字,用itoA
函數把數字轉換成字元串。
f, _ := strconv.ParseFloat("1.234", 64)
//inputstring是一個用字元串表示的數字浮點數 bitSize是int類型的參數精度值。對於 float32 可以是 32,對於 float64 可以是 64
//這個函數總是返回兩個值。返回的float64值包含一個浮動數。如果需要,我們可以轉換為float32值。如果不能將字元串轉換為浮動數,則返回錯誤值*NumError。
fmt.Println(f)
n, _ := strconv.ParseInt("12345", 10, 64)
//第二個參數代表進位
fmt.Println(n)
n1, _ := strconv.ParseInt("0x1000", 0, 64)
//值為2~36,如果為0,則會根據字元串自動判斷前置為"0x"的是16進位;前置為"0"的是8進位;其餘的為10進位
fmt.Println(n1)
n2, _ := strconv.Atoi("123")
fmt.Println(n2)
n3, err := strconv.Atoi("AAA")
fmt.Println(n3, err)
n4 := strconv.Itoa(234)
fmt.Println(n4)
進程信息
func main() {
fmt.Println(os.Args)
fmt.Println(os.Getenv("PATH"))
fmt.Println(os.Setenv("AA", "BB"))
buf, err := exec.Command("grep", "127.0.0.1", "/etc/hosts").CombinedOutput()
//command裡面的參數第一個是執行命令,後面所有全部都是參數
if err != nil {
panic(err)
}
fmt.Println(string(buf))
}
Getenv
函數會檢索並返回名為 key 的環境變數的值。如果不存在該環境變數則會返回空字元串。
Setenv
函數可以設置名為 key 的環境變數,如果出錯會返回該錯誤。
本文來自博客園,作者:ivanlee717,轉載請註明原文鏈接:https://www.cnblogs.com/ivanlee717/p/17397393.html