1. 程式人生 > >Golang語法的踩坑總結(持續更新中)

Golang語法的踩坑總結(持續更新中)

*本來這篇是想寫docker的基本操作總結的。。。想想還是寫這個吧。。。→_→*

  • 變數宣告使用 := 方式時,左值必須是未宣告的,否則會出現編譯錯誤

    //.\main.go:8:4: no new variables on left side of :=
    package main
    
    import "fmt"
    
    func main() {
        var a int = 10
        var b int = 20
        b := 30
    
        fmt.Print(a, b)
    }
  • 變數聲明瞭,就必須要使用,否則會出現編譯錯誤

    //.\main.go:7:6: b declared and not used
    package main import "fmt" func main() { var a int = 10 var b int = 20 fmt.Print(a) }
  • const修飾符的作用範圍為同時修飾的所有常量

    //.\main.go:7:4: cannot assign to a
    //.\main.go:8:4: cannot assign to b
    package main
    
    import "fmt"
    
    func main() {
        const a, b int = 10, 20
        a = 10
        b = 20
    
        fmt.Print(a, b)
    }
    
  • ++自增和- -自減運算子類比C語言,相當於前置的自增和自減,而且go語言中不區分前置或後置

    //.\main.go:9:2: syntax error: unexpected ++, expecting }
    package main
    
    import "fmt"
    
    func main(){
        var a int = 10
        var b int = 20
    
        ++a
        b++
    
        fmt.Print(a, b)
    }
  • 不能使用++自增或- -自減運算子初始化變數和對變數賦值

    //.\main.go:7:15: syntax error: unexpected ++ at end of statement
    //.\main.go:10:7: syntax error: unexpected ++ at end of statement package main import "fmt" func main(){ var a int = 10 var b int = a++ var c int = 20 c = a++ fmt.Print(a, b, c) }
  • if…else 語句中的 else 必須和 if 的 ’ } ’ 在同一行,否則編譯錯誤

    //.\main.go:11:2: syntax error: unexpected else, expecting }
    package main
    
    import "fmt"
    
    func main() {
        var a int = 30
    
        if a < 20 {
            fmt.Print("a<20")
        } 
        else {
            fmt.Print("a>=20")
        }
    }
  • switch 中的 case和default分支不用新增break

    //程式碼執行成功
    package main
    
    import "fmt"
    
    func main() {
        var a int = 10
    
        switch a {
        case 1:
            fmt.Println("1")
        case 2:
            fmt.Println("2")
        case 10:
            fmt.Println("10")
        default:
            fmt.Println("unknow")
        }
    }
  • switch 中 也可以不用新增表示式

    //程式碼執行成功
    package main
    
    import "fmt"
    
    func main() {
        var a int = 10
    
        switch {
        case a == 1:
            fmt.Println("1")
        case a == 2:
            fmt.Println("2")
        case a == 10:
            fmt.Println("10")
        default:
            fmt.Println("unknow")
        }
    }
  • switch的case分支的常量表達式可以同時測試多個值

    
    //程式碼執行成功
    package main
    
    import "fmt"
    
    func main() {
        var a int = 10
    
        switch {
        case a == 1, a == 2:
            fmt.Println("1 or 2")
        case a == 10, a == 20:
            fmt.Println("10 or 20")
        case a == 100, a == 200:
            fmt.Println("100 or 200")
        default:
            fmt.Println("unknow")
        }
    }
  • switch 語句還可以被用於 type-switch 來判斷某個 interface 變數中實際儲存的變數型別

    package main
    
    import "fmt"
    
    func main() {
        var x interface{}
    
        switch i := x.(type) {
        case nil:
            fmt.Printf("%T", i)
        case int:
            fmt.Printf("int")
        case float64:
            fmt.Printf("float64")
        case func(int) float64:
            fmt.Printf("func(int)")
        case bool, string:
            fmt.Printf("bool or string")
        default:
            fmt.Printf("unknow")
        }
    }
  • select 語句。。這個現在還沒看懂。。先MARK

    Learning...
  • for迴圈語句range格式,遍歷陣列

    //i為下標
    //x為元素的值
    //0 1
    //1 2
    //2 3
    //3 4
    //4 5
    package main
    
    import "fmt"
    
    func main() {
        var number = [5]int{1, 2, 3, 4, 5}
        for i, x := range number {
            fmt.Println(i, x)
        }
    }
  • for迴圈語句和C語言中的while迴圈語句比較

    //0 1 2 3 4 5 6 7 8 9
    package main
    
    import "fmt"
    
    func main() {
        var a int = 0
        for a < 10 {
            fmt.Printf("%d ", a)
            a++
        }
    }
  • for迴圈語句和C語言中的for迴圈語句比較

    //0 1 2 3 4 5 6 7 8 9
    package main
    
    import "fmt"
    
    func main() {
        var a int = 0
        for a = 0; a < 10; a++ {
            fmt.Printf("%d ", a)
        }
    }
  • 函式的結構與C語言中的函式結構有很大不同,函式呼叫相似

    //10 10
    //true
    package main
    
    import "fmt"
    
    func fun(num1 *int, num2 *int) bool {
        fmt.Println(*num1, *num2)
        if *num1 == *num2 {
            return true
        } else {
            return false
        }
    }
    
    func main() {
        var a int = 10
        var b int = 10
    
        var flag bool = fun(&a, &b)
        fmt.Print(flag)
    }
  • 函式可以同時返回多個值

    //hello world
    package main
    
    import "fmt"
    
    func fun(str1 string, str2 string) (string, string) {
        return str2, str1
    }
    
    func main() {
        str1, str2 := fun("world", "hello")
        fmt.Println(str1, str2)
    }
    
  • 函式可以作為值使用,神奇~

    //-1
    package main
    
    import "fmt"
    
    func main() {
        tmp := func(x int) int {
            return -x
        }
        fmt.Print(tmp(1))
    }
  • 函式支援匿名函式,可作為閉包。匿名函式是一個”內聯”語句或表示式。匿名函式的優越性在於可以直接使用函式內的變數,不必申明。

    //1 2 3
    package main
    
    import "fmt"
    
    func first() func() int {
        i := 0
        return func() int {
            i++
            return i
        }
    }
    
    func main() {
        tmp := first()
        fmt.Println(tmp(), tmp(), tmp())
    }
  • 函式也可以成為自定義型別的一個方法

    //10 abc
    package main
    
    import "fmt"
    
    //自定義型別
    type student struct {
        num  int
        name string
    }
    
    //方法getNum
    func (stu student) getNum() int {
        return stu.num
    }
    
    //方法getName
    func (stu student) getName() string {
        return stu.name
    }
    
    func main() {
        var st student
        st.num = 10
        st.name = "abc"
        //物件呼叫其方法
        fmt.Println(st.getNum(), st.getName())
    }
  • 陣列的宣告、初始化、賦值、訪問

    //[0 0 0 0 0 0 0 0 0 0]
    //100 1 2 3 4 5 6 7 8 9 [100 1 2 3 4 5 6 7 8 9]
    package main
    
    import "fmt"
    
    func main() {
        var arr [10]int
        var number = [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
        number[0] = 100
    
        fmt.Println(arr)
        var i int = 0
        for i = 0; i < 10; i++ {
            fmt.Printf("%d ", number[i])
        }
    
        fmt.Println(number)
    }
    
  • 二維陣列的初始化

    //[[1 2 3] [4 5 6] [7 8 9]]
    package main
    
    import "fmt"
    
    func main() {
        var number = [3][3]int{
            {1, 2, 3},
            {4, 5, 6},
            {7, 8, 9}}
        fmt.Println(number)
    }
  • 函式引數為陣列,必須同時顯示的寫出陣列元素個數或同時隱藏陣列的元素個數

    //0 1 2 3 4 5 6 7 8 9 10
    package main
    
    import "fmt"
    
    func getNum(number []int) int {
        var i int = 0
        for i = 0; i < 10; i++ {
            fmt.Printf("%d ", number[i])
        }
        return len(number)
    }
    
    func main() {
        var number = []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
        num := getNum(number)
        fmt.Println(num)
    }
    //0 1 2 3 4 5 6 7 8 9 10
    package main
    
    import "fmt"
    
    func getNum(number [10]int) int {
        var i int = 0
        for i = 0; i < 10; i++ {
            fmt.Printf("%d ", number[i])
        }
        return len(number)
    }
    
    func main() {
        var number = [10]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
        num := getNum(number)
        fmt.Println(num)
    }
  • 指標陣列的初始化和使用

    //0 1 2 3 4 5 6 7 8 9 
    package main
    
    import "fmt"
    
    func main() {
        var number = [10]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
        var num [10]*int
    
        for i := 0; i < 10; i++ {
            num[i] = &number[i]
        }
    
        for i := 0; i < 10; i++ {
            fmt.Printf("%d ", *num[i])
        }
    }
  • 二級指標的初始化和使用

    //10 10 10
    package main
    
    import "fmt"
    
    func main() {
        var i int = 10
        var ptr1 *int = &i
        var ptr2 **int = &ptr1
    
        fmt.Printf("%d %d %d", i, *ptr1, **ptr2)
    }
  • 結構體的定義和初始化方式,注意結構體變數和結構體指標變數訪問結構體成員時只有 . 一種方式,此處和C語言的結構體語法不同

    //111
    //zhangsan
    //man
    //20
    //111
    //zhangsan
    //man
    //20
    package main
    
    import "fmt"
    
    type studentInfo struct {
        id   int
        name string
        sex  string
        age  int
    }
    
    func getInfo(stu studentInfo) {
        fmt.Println(stu.id)
        fmt.Println(stu.name)
        fmt.Println(stu.sex)
        fmt.Println(stu.age)
    }
    
    func getInfoByPtr(stuPtr *studentInfo) {
        fmt.Println(stuPtr.id)
        fmt.Println(stuPtr.name)
        fmt.Println(stuPtr.sex)
        fmt.Println(stuPtr.age)
    }
    
    func main() {
    
        var stu studentInfo
        stu.id = 111
        stu.name = "zhangsan"
        stu.sex = "man"
        stu.age = 20
        getInfo(stu)
        var stuPtr *studentInfo = &stu
        getInfoByPtr(stuPtr)
    }
  • 切片(Slice),長度不固定,可以理解為動態陣列。Slice有兩個屬性:length即當前元素的容量大小,capacity即可以最大容納元素的容量大小。Slice的定義如下

    //make([]T, length, capacity)
    //len = 0 cap = 0, slice = []
    //len = 10 cap = 10, slice = [0 0 0 0 0 0 0 0 0 0]
    //len = 10 cap = 10, slice = [0 0 0 0 0 0 0 0 0 0]
    //len = 5 cap = 10, slice = [0 0 0 0 0]
    package main
    
    import "fmt"
    
    func printSlice(slice []int) {
        fmt.Printf("len = %d cap = %d, slice = %v\n", len(slice), cap(slice), slice)
    }
    
    func main() {
        var slice1 []int
        printSlice(slice1)
    
        var slice2 = make([]int, 10)
        printSlice(slice2)
    
        var slice3 = make([]int, 10, 10)
        printSlice(slice3)
    
        slice4 := make([]int, 5, 10)
        printSlice(slice4)
    }
  • Slice的初始化如下:startIndex代表起始下標,endIndex代表終止下標,但在初始化時的實際範圍是startIndex~endIndex-1。
    預設endIndex表示一直到最後一個元素,預設startIndex表示從第一個元素開始。
    當startIndex不是從arr[0]開始時,會將新切片的cap值改變為:原cap的值減startIndex。

    //s := arr[startIndex:endIndex] 
    //len = 10 cap = 10, slice = [0 1 2 3 4 5 6 7 8 9]
    //len = 10 cap = 10, slice = [0 1 2 3 4 5 6 7 8 9]
    //len = 10 cap = 10, slice = [0 1 2 3 4 5 6 7 8 9]
    //len = 2 cap = 9, slice = [1 2]
    //len = 9 cap = 9, slice = [1 2 3 4 5 6 7 8 9]
    //len = 3 cap = 10, slice = [0 1 2]
    //len = 2 cap = 8, slice = [2 3]
    package main
    
    import "fmt"
    
    func printSlice(slice []int) {
        fmt.Printf("len = %d cap = %d, slice = %v\n", len(slice), cap(slice), slice)
    }
    
    func main() {
        var slice1 = []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
        printSlice(slice1)
    
        slice2 := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
        printSlice(slice2)
    
        //陣列arr
        var arr = [10]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
        slice3 := arr[:]
        printSlice(slice3)
    
        slice4 := arr[1:3]
        printSlice(slice4)
    
        slice5 := arr[1:]
        printSlice(slice5)
    
        slice6 := arr[:3]
        printSlice(slice6)
    
        slice7 := slice5[1:3]
        printSlice(slice7)
    }
  • 未初始化的切片Slice預設為nil,len為0,cap為0

    //len = 0, cap = 0, slice = []
    //slice is nil
    package main
    
    import "fmt"
    
    func printSlice(slice []int) {
        fmt.Printf("len = %d, cap = %d, slice = %v\n", len(slice), cap(slice), slice)
    }
    
    func main() {
        var slice []int
        printSlice(slice)
    
        if slice == nil {
            fmt.Printf("slice is nil\n")
        }
    }
  • Slice切片的append()追加和copy()拷貝。
    當切片長度len等於切片容量cap時,再append()追加資料,此時切片cap容量增長,且預設擴容2倍。

    //len = 0, cap = 0, slice = []
    //len = 1, cap = 1, slice = [0]
    //len = 2, cap = 2, slice = [0 1]
    //len = 5, cap = 6, slice = [0 1 2 3 4]
    //len = 5, cap = 12, slice = [0 1 2 3 4]
    package main
    
    import "fmt"
    
    func printSlice(slice []int) {
        fmt.Printf("len = %d, cap = %d, slice = %v\n", len(slice), cap(slice), slice)
    }
    
    func main() {
        var slice []int
        printSlice(slice)
    
        //此時cap預設擴容2倍
        slice = append(slice, 0)
        printSlice(slice)
    
        //此時cap預設擴容2倍
        slice = append(slice, 1)
        printSlice(slice)
    
        //此時cap擴容規則出現變化,同時append追加多個數據時,cap會擴容到向上最近的偶數數值,以減少cap容量的浪費
        slice = append(slice, 2, 3, 4)
        printSlice(slice)
    
        slice2 := make([]int, len(slice), cap(slice)*2)
        copy(slice2, slice)
        printSlice(slice2)
    }
  • Slice切片的append()並沒有改變引數中的原切片,而是改變了接受返回值的切片

    //[1 2 8 4]
    //[1 2 8 4]
    //[1 2 8 4]
    //[1 2 9 4 5]
    package main
    
    import "fmt"
    
    func main() {
        original := []int{1, 2, 3, 4} //a slice with a len and cap of 4
        other := original
        other[2] = 8
        fmt.Println(original)
        fmt.Println(other)
    
        other = append(original, 5)
        other[2] = 9
        fmt.Println(original)
        fmt.Println(other)
    }
  • range(範圍)用來迴圈迭代array(陣列)、slice(切片)、channel(通道)、map(集合)

    //slice
    package main
    
    import "fmt"
    
    func main(){
        nums := []int{1, 2, 3}
        sum := 0
        for _, num := range nums{
            sum += num
        }
        fmt.Print(sum)
    }
    
    //slice
    package main
    
    import "fmt"
    
    func main(){
        kvs := map[string]string{"1": "one", "2": "two"}
    
        for k, v := range kvs{
            fmt.Printf("%s -> %s\n", k, v)
        }
    }
    
  • map是無序的鍵值對集合,delete函式刪除map中的元素

    package main
    
    import "fmt"
    
    func main(){
        //定義map集合
        var studentName map[int]string
        //初始化建立集合
        studentName = make(map[int]string)
    
        studentName[0] = "zhangsan"
        studentName[1] = "lisi"
        studentName[2] = "wangwu"
        //由於map是hash表實現的,所以每次的迭代結果不確定
        for ID := range studentName{
            fmt.Printf("%d -> %s\n", ID, studentName[ID])
        }
        //刪除key為0的元素
        delete(studentName, 0)
        fmt.Println("delete", 0)
    
        for ID := range studentName{
            fmt.Printf("%d -> %s\n", ID, studentName[ID])
        }
    }
    
  • interface介面,和JAVA中的介面相似

    package main
    
    import (
        "fmt"
    )
    
    type Action interface{
        sleep()
        eat()
    }
    
    type Human struct{
    
    }
    
    func(hum Human) sleep(){
        fmt.Println("human sleeping")
    }
    
    func(hum Human) eat(){
        fmt.Println("human eating")
    }
    
    type Dog struct{
    
    }
    
    func(dog Dog) sleep(){
        fmt.Println("dog sleeping")
    }
    
    func(dog Dog) eat(){
        fmt.Println("dog eating")
    }
    
    func main(){
    
        var action Action
    
        action = new(Human)
        action.sleep()
    
        action = new(Dog)
        action.eat()
    }
    
  • 錯誤處理

    package main
    
    import (
        "fmt"
    )
    
    // 定義一個 DivideError 結構
    type DivideError struct {
        dividee int
        divider int
    }
    
    // 實現 `error` 介面
    func (de *DivideError) Error() string {
        strFormat := `
        Cannot proceed, the divider is zero.
        dividee: %d
        divider: 0
    `
        return fmt.Sprintf(strFormat, de.dividee)
    }
    
    // 定義 `int` 型別除法運算的函式
    func Divide(varDividee int, varDivider int) (result int, errorMsg string) {
        if varDivider == 0 {
            dData := DivideError{
                dividee: varDividee,
                divider: varDivider,
            }
            errorMsg = dData.Error()
            return
            } else {
            return varDividee / varDivider, "no error"
        }
    }
    
    func main() {
    
        // 正常情況
        result, errorMsg := Divide(100, 10)
    
        if errorMsg == "no error" {
            fmt.Println("100/10 = ", result, errorMsg)
        }
        // 當被除數為零的時候會返回錯誤資訊
        result, errorMsg = Divide(100, 0)
    
        if errorMsg != "no error" {
            fmt.Println("errorMsg is: ", result, errorMsg)
        }
    }
    

相關推薦

Golang語法總結持續更新

*本來這篇是想寫docker的基本操作總結的。。。想想還是寫這個吧。。。→_→* 變數宣告使用 := 方式時,左值必須是未宣告的,否則會出現編譯錯誤 //.\main.go:8:4: no

weex 持續更新……

消失了一個月,努力為新專案倒騰 weex 中,記錄一下遇到的問題。之後還會持續更新~ 目前,我使用的 weex 都是在整合Weex到Android來做的,專案使用的是 weex-toolkit

關於Yii2的MVC的視圖總結持續更新

gif pre lis frontend dbo register front reg open 一、首先在控制器中,將處理好的數據發送給前臺: $this->layout = ‘base‘; 這裏填寫視圖的模板文件(可以不寫這行代碼,如果不寫,默認為views/la

前端開發工程師從入門到精通學習過程及資源總結持續更新

開發實戰 set dex 從入門到精通 main 知識 uno 基礎入門 易雲 職位名稱:前端開發工程師 學習概要:1、先了解基礎,html/css/JavaScript是基礎。html/css就是做靜態頁面的,javascript是做動態的。 2、學習框架:jQuery(

Java常見異常總結持續更新......

1.類未找到 Exception in thread "main" java.lang.NoClassDefFoundError:類名 Caused by: java.lang.ClassNotFoundException:類名 這種異常未未發現類異常,是由於編譯的時候未找到該類而報異常

計算機專業學習資料總結~持續更新

今天為了複習離散數學,想著上網上找份課本答案(老師沒有給答案),結果那本書的配套題解的PDF大多數都是來自CSDN社群的,CSDN下載需要積分,要麼開通VIP,那VIP的費用實在不是我等窮學生所能支付得起的,我靈機一動便想到了萬能的淘寶賣家果然有賣CSND積分的,花了1塊3,很順利地下載了我想要的輔導書,之前

java+selenium的使用方法歸納總結持續更新

selenium的使用 第一步:獲取selenium的jar包及驅動瀏覽器的驅動 在獲取selenium的jar包和瀏覽器的驅動包時,要對照她們的版本號 通過下面可檢視谷歌的版本對應 java+selenium的入門 案例 selenium包 谷歌驅動包 火狐驅動包 IE驅動包

iOS開發除錯技巧總結持續更新

作者:乞力馬紮羅的雪  原文 對於軟體開發而言,除錯是必須學會的技能,重要性不言而喻。對於除錯的技能,基本上是可以遷移的,也就是說你以前在其他平臺上掌握的很多除錯技巧,很多也是可以用在iOS開發中。不同語言、不同IDE、不同平臺的除錯,有同性也有個性。今

遇到的錯誤總結持續更新

一、Sql server 2008 R2 配置管理工具服務顯示遠端過程呼叫失敗:0x800706be 通過網上查,才知道是因為SQL Server2008 與VS2014 共存的問題,當你電腦中同時裝了這兩樣東西,SQL 就會出現上圖中的情況。   解決辦法:從控制面板或者其他輔助軟體中找

CNN的經典文章要點總結持續更新

AlexNet(2012) 資料: 輸入要求:256*256 結構包含8層帶權重的層:5層卷積層+3層全連線層 引數:batchsize= 128,momentum=0.9,weight decay=0.0005 具

app崩潰的原因 和 提前測試流程/方法 和出現崩潰後怎麼定位和處理 總結持續更新

首先,崩潰有幾種情況: 閃退 提示停止執行 無響應 ( 不同情況雖然沒有嚴格意義上區分開引起原因,但是都有側重。在之後的工作中,我會實時補充統計。) 1.介面返回值 [直接原因]:ap

前端開發日誌持續更新。。。

1、火狐瀏覽器對event的支援,如果var e = window.event就會出錯,解決辦法:var e = event || window.event; 2、event.target和event.currentTarget的區別 3、使用axios進行跨域請求時要對option請求時,後端要對

Vue2.x 記錄持續更新

踩坑少年歡樂多0.0記錄下自己開發過程中遇到的坑,避免以後遇到了又一臉懵逼。(之前已經踩過很多坑了,沒有及時記錄,之後優化程式碼的時候再看到或者後續開發中遇到坑會更新到文章中。)computed修改data返回的資料出處是黃神的課程,原始碼是vue1.x,在2.x版本就會有這

golang持續更新....

使用golang開發新專案有一段時間了,現在逐漸對go有點失望了,但還好沒有絕望。 最開始草草翻閱《go語音程式設計》( 許式偉)時,最讓我眼前一亮的其實並不是協程(這個已經聽了太多太多…),而是其中對json的marshal和unmarshal,然後就瞭解到

LeetCode 總結 持續更新。。。。

總結 get ngs multiply log 。。 icu ble 更新 No. Name Acceptance Difficulty Star 43 Multiply Strings 27.3% medium 3.5 90 Subsets II 36.5%

golang開發常用開源項目工具持續更新

golang開源項目 golang工具 本人在日常golang項目開發中,用到了一些第三方開源庫,大多都是優秀的開源項目,源碼值得認真閱讀研究。在此記錄用到的一些庫:解析配置文件go-ini https://github.com/go-ini/inigolang開發常用開源項目工具(持續更新中)

總結Spring框架擴充套件點bean生命週期的擴充套件點持續更新...

面向業務開發的時候,程式設計師需要明白業務的邏輯,並設計程式碼結構。而在進行中介軟體開發的時候,則需要明白框架的邏輯,進行開發。 所以要開發提供給spring的中介軟體,需要知道spring中有哪些擴充套件點,好在對應的地方插入我們的功能。 1. Spring容器初始化b

hdoj刷題經驗總結持續更新ing

(語言採用c++)1、輸出如何保留兩位小數#include<iostream>#include<iomanip>using namespace std;void main(){float result=2.355; printf("%.2f\n",re

總結了一些新的面試題,包含答案持續更新

Java根底● 集合類以及集合框架;HashMap與HashTable完成原理,執行緒平安性,hash抵觸及處置演算法;ConcurrentHashMap;- Collection 集合的根介面+Set 繼承類,不能包含重複元素,無序+List 繼承類,可以包含重複元素,

LeetCode刷題總結持續更新。。。

1、迴文字元 返回字串是否迴文結構 def huiwen(str): if len(str) == 1: return True elif len(str)