go相當詳細的基礎語法

来源:https://www.cnblogs.com/ivanlee717/archive/2023/05/13/17397393.html
-Advertisement-
Play Games

運行命令 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")
}

img

基礎語法

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))
}
  1. 定義變數可分為:var+變數定義,變數 :=
  2. 定義常量時沒有類型限制,其可根據上下文自行進行定義

img

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當中添加變數的定義

img

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

img

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,運行後面的語句

img

數組

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值

img

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)
}

img

函數

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"))
}

函數定義時,參數需要類型定義,以及返回時的類型。如果有多個函數返回值,則分別說明類型

img

指針

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)
}

img

結構體

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))
}

img

字元串格式化

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

img

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)
}

img

  • 只要是可導出成員(變數首字母大寫),都可以轉成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())
}

img

數字和字元轉換

在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)

img

進程信息

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))
}

更多相關os模塊用法

Getenv 函數會檢索並返回名為 key 的環境變數的值。如果不存在該環境變數則會返回空字元串。

Setenv 函數可以設置名為 key 的環境變數,如果出錯會返回該錯誤。

img

本文來自博客園,作者:ivanlee717,轉載請註明原文鏈接:https://www.cnblogs.com/ivanlee717/p/17397393.html


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Java設計模式【單例模式】 單例模式 單例模式(Singleton Pattern)是一種創建型設計模式,其主要目的是確保一個類只有一個實例,並提供對該實例的唯一訪問點。 優缺點 優點: 提供了對唯一實例的受控訪問。 由於在系統記憶體中只存在一個對象,因此可以節約系統資源。 缺點: 單例類的擴展有很 ...
  • 本文儘可能對GC的情況進行簡要表述,目標是用最少的描述來完整闡明JDK8 Java Hotspot VM目前支持的各種GC方式及其調優方法。 為精簡行文內容,正文中不包含GC觀測手段的介紹,讀者可以參考 [Java Platform, Standard Edition HotSpot 虛擬機垃圾收集... ...
  • _Java 平臺標準版 HotSpot 虛擬機垃圾收集調整指南_ 描述了 Java HotSpot 虛擬機 (Java HotSpot VM) 中包含的垃圾收集方法,並幫助您確定最適合您需要的方法。 本文檔適用於希望提高應用程式性能的應用程式開發人員和系統管理員,尤其是那些處理大量數據、使用多線程... ...
  • 首先值得說明的是,在這個項目幾乎完成之際,筆者才愈發體會到了硬體思維和軟體思維的雲泥之別。不幸的是,在此項目的實現過程中,絕大部分代碼的思維仍然是軟體思維,因此該項目主要模塊的設計部分可能並不能體現硬體操作的獨到之處,不符合硬體工程師的基本設計思維,所以此主題文章僅用於學習交流以及記錄一次FPGA項 ...
  • 剪貼板是個啥就不用多介紹了,最直觀的功能是實現應用程式之間數據共用。就是咱們常說的“複製”、“粘貼”功能。 在 Qt 中,QClipboard 類提供了相關 API 讓應用程式具備讀/寫剪貼板的能力。數據通過 QMimeData 類包裝。該類使用 MIME 類型來標識數據。比如,要包裝的數據是純文本 ...
  • golang支持兩種隨機數生成方式: math/rand // 偽隨機 crypto/rand // 真隨機 math/rand的用法:rand.Intn(100)。這個起始位置是由一個seed決定的,預設是從1開始。為了儘量隨機性,那麼我們可以每次使用不同的seed來啟動程式,就可以保證每次啟動都 ...
  • 最近熟悉 go 項目時,發現項目中有用到 github.com/yuin/gopher-lua 這個包,之前並沒有接觸過,特意去看了官方文檔和找了些網上的資料,特此記錄下。 本次介紹計劃分為兩篇文章,這一次主要介紹 github.com/yuin/gopher-lua 這個包的介紹以及基礎使用,下一 ...
  • AutoWiredAnnotationBeanPostProcessor 執行依賴註入的時候(解析@Autowired)調用了postProcessProperties 方法 這個方法首先要找到哪些屬性,方法被標註了@Autowired註解,把這些數據添加到 InjectMetadata中,然後調用 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...