GoLang 環境部署

環境部署

Go編譯器

Downloads - Go

​ 安裝位置:

C:\Program Files\Go

image-20210502222044326

其他配置

  • 創建一個任意的目錄 GolangProjects,目錄結構如下

    GolangProjects
    
    --bin
    
    --- crm.exe //主程序入口文件
    
    --pkg
    
    --- commlib.A //包文件
    
    --src
    

配置環境變量

  • 添加環境變量 GOROOT : C:\Program Files\Go Go 編譯器的安裝目錄
  • 添加環境變量 GOBIN : E:\Code\GoLangProjects\bin 方便直接 Go
  • 添加環境變量 GOPATH: E:\Code\GoLangProjects

vs code 配置環境

tools 怎麼來的

Clone 無需多言

推薦使用:SourceTree ,主要界面看着挺爽

怎麼擺放

在本地go_path 目錄下新建文件夾,如下結構

-- go path
--- bin
--- pkg
--- src
---- github.com
------ Go-zh
------- tools //https://github.com/Go-zh/tools.git
---- golang.org
----- x
------ mod //https://github.com/golang/mod.git
------ sys //https://github.com/golang/sys.git
------ tools //https://github.com/golang/tools.git
------ xerrors //https://github.com/golang/xerrors.git

安裝命令

打開 go-path 目錄的下的src 目錄,地址欄裏輸入 cmd ,啓動終端,輸入如下命令:

1. go install golang.org/x/tools/cmd/guru
2. go install golang.org/x/tools/cmd/gorename
3. go install golang.org/x/tools/cmd/fiximports
4. go install golang.org/x/tools/cmd/gopls 
5. go install golang.org/x/tools/cmd/godex

注意:

我個人在第4點出錯了,原因是因爲英文官方的tools中按照位置找過去沒有gopls;

百度過後才下載的中文社區的,由此纔看到前面的目錄結構。

所以到這要安裝gopls,執行如下命令:

go install github.com/Go-zh/tools/cmd/gopls

vscode運行代碼

  • 一般姿勢:

    啓動vscode終端,cd 到 go-path 目錄下的src,再找到指定指定go文件,例如:go run app.go

  • 進階姿勢:

    啓動vscode擴展,安裝 code run 插件,安裝按完重啓編輯器,只需要右鍵選擇code run 即可,或者快捷鍵 ctrl + alt + n

運行代碼

src 目錄下添加go文件

-src

--crm

---app.go

-- app.go

package  main

import "fmt"

func main()  {
	fmt.Printf("Hello Go~ 叫爸爸~")
}

--commlib

---page

package commlib

func Add(i int ,j int)int {
	return i+j
}

運行有三種方式:

​ 進入項目目錄執行:

  • go run app.go
  • go build app.go 執行完此命令後,會在同級目錄下面添加同名exeapp.exe可執行程序,然後cmd中執行exe程序即可。與第一種方式相同,只是go run 相當於一起把此方式中的兩步驟一次執行完畢。
  • go install 執行完命令後,會在外面那個Bin 文件夾生產一個exe可執行文件,crm.exe,也可以在cmd命令中執行,於上面第二種方式的區別在於,會在Bin文件夾中生成exe可執行文件。但是如果生成的項目不是主程序入口、只有方法的話,就會生成包文件commlib.A文件,類似於C# 中類,存放在bin文件夾的同級目錄pkg文件夾中。

Go 包管理

初識包管理

  • 一個文件夾也可以稱之爲一個包
  • 在文件夾(包)中可以創建多個文件
  • 在同一個包下的每個文件中必須指定包名稱且相同

包的分類

  • main包,如果是main包,必須寫一個 main函數,以此作爲程序的入口,又稱爲主函數,編譯生成後會生成一個可執行文件。
  • main

調用包

調用包文件內的方法:

package  main

import (
	"commlib" //這裏會引入包
	"fmt"
	"strconv" //引入包
)

func main()  {
    //println 自帶輸出換行
	fmt.Println("Hello Go~ ")
	//調用
	var num int = commlib.Add(1,6)
    //strconv.itba()方法,int 轉 string
	fmt.Println(strconv.Itoa(num))

}
package commlib

func Add(i int ,j int)int {
	return i+j
}

包定義規範

  • 定義包文件之後,包內的函數首字母必須得大寫
  • 大寫和小寫的區別:
    • 大寫:類似於C# 中的 public 修飾符,包的外部可以進行調用
    • 小寫:類似於C# 中的 internal修飾符,僅限於包內部使用

截圖

image-20210505225640086

​ 2021.05.05

基礎知識

輸出

在終端輸出前置語言例如:請輸入賬戶名或者密碼等等...

  • 內置函數
    • print
      • 默認打印兩個print 是連在一起的,如果想要達到換行效果需要在內容尾部加上\n
    • println
      • 默認打印兩個println 是自帶換行效果的
  • fmt
    • fmt.print
      • 效果通內置函數 print 相仿
    • fmt.println
      • 同上,平時推薦使用此方法
    • fmt.println擴展:
      • fmt.println("我叫","Harris","年齡","18") 中間自帶空格
      • 格式化顯示:
        • fmt.printF()
  • 在以上兩種方式的輸出中推薦使用 fmt,原因:
    • Golang官方給出的回答是,在以後的規劃中,不保證內置函數可以繼續使用,爲防止後面禁用內置函數後,代碼出問題。

註釋

  • 單行註釋 //
  • 多行註釋 /* */
  • GoLand 快捷鍵 Ctrl+?

變量

  • 概述

    • Go 是靜態類型語⾔,不能在運⾏期改變變量類型
    • 使⽤關鍵字 var 定義變量,⾃動初始化爲零值。如果提供初始化值,可省略變量類型,由 編譯器⾃動推斷。
    • 聲明的變量必須使用 如果聲明不使用,則報錯 編譯器會將未使⽤的局部變量當做錯誤
  • 變量的作用域

    • ​ 全局變量:沒有寫在函數內的變量,稱之爲全局變量,個人理解。

      var name string = "Harris"
      var name = "Harris"
      var {
          v1 = "a"
          v2 = "b"
          v3 = 18
          v4 int
      }
      name := "Harris" //這種不行滴
      
    • 局部變量:函數內的變量 局部就和C#差不多了

      func main(){
          var name string = "Harris"   
          name := "Harris"    
          var name = "Harris"    
          var{
              name = "Harris"
              age = 18
          }
      }
      
    • 多變量賦值時,先計算所有相關值,然後再從左到右依次賦值

      data, i := [3]int{0, 1, 2}, 0
      i, data[i] = 2, 100 // (i = 0) -> (i = 2), (data[0] = 100)
      fmt.Println(i,data)
      //結果:2 [100 1 2]
      
    • 特殊只寫變量 "_",⽤於忽略值佔位

      func test() (int, string) {
       	return 1, "abc"
      }
      
      func main() {
           _, s := test()
           fmt.Println(s)
          //結果:abc
      }
      
    • 編譯器會將未使⽤的局部變量當做錯誤

      func main() {
       	i := 0 // Error: i declared and not used。(可使⽤ "_ = i" 規避)
      }
      

常量

  • 常量值必須是編譯期間固定的數字、字符串、布爾值

    const x,y int = 1,2     //多常量初始化
    
    const z = "Hello World" //類型推斷
    
    const{
        a,b = 1,2
        c bool = true
    }
    
    func main(){
        const x = "xxxx" //這個時候如果沒有使用上述已經定義好的常量,不會報錯
    }
    
  • 常量可以使用在編譯期間確定的函數

    const a,b int =1,2
    
    const c = "abc"
    
    const x = len(c)
    
    const y = unsafe.Sizeof(x) //這個方法是用來計算字節的,64爲系統中,字符串和整形的字節一個都是8
    
    fmt.Println(a)
    
    fmt.Println(b)
    
    fmt.Println(c)
    
    fmt.Println(x)
    
    fmt.Println(y)
    
    //結果:
    /*
    1
    2
    abc
    3
    8*/
    

枚舉

  • 關鍵字 iota 定義常量組中從 0 開始按⾏計數的⾃增枚舉值。

    const(
        Sunday = iota   //0
        Monday          //1,通常省略後面的表達式
        Tuesday			//2
        Wednesday		//3
        Thursday		//4
        Friday			//5
        Saturday		//6
    )
    const (
        _ = iota // iota = 0
        KB int64 = 1 << (10 * iota) // iota = 1  << 是左移運算符
        MB // 與 KB 表達式相同,但 iota = 2
        GB
        TB
    )
    
    fmt.Println(KB,MB,GB) //1024 1048576 1073741824
    
  • 在同⼀常量組中,可以提供多個 iota,它們各⾃增⻓。

    const (
        A, B = iota, iota << 10 // 0, 0 << 10
        C, D // 1, 1 << 10
    )
    
    fmt.Println(A,B,C,D) //0 0 1 1024
    
  • 如果 iota ⾃增被打斷,須顯式恢復

    const (
        A = iota // 0
        B // 1
        C = "c" // c
        D // c,與上⼀⾏相同。
        E = iota // 4,顯式恢復。注意計數包含了 C、D 兩⾏。
        F // 5
    )
    
    fmt.Println(A,B,C,D,E,F)//0 1 c c 4 5
    
  • 可通過⾃定義類型來實現枚舉類型限制

    type Color int
    
    const (
         Black Color = iota
         Red
         Blue
    )
    
    func test(c Color)Color {
        return c
    }
    
    func main() {
         c := Black
         fmt.Println(test(c))     // 0
         x := 1
         test(x) // Error: cannot use x (type int) as type Color in function argument;寫的時候就會報錯沒法轉換
    }
    

數據類型

image-20210515232851239

  • 空指針值 nil,⽽⾮ C/C++ NULL。

引用類型

切片(Slice)

實現類似動態數組的功能

package commlib

import "fmt"

func SliceTest1()  {
	x:=make([]int,0,5)//聲明一個容量爲5的切片

	for i:=0;i<8;i++ {
		x= append(x,i) //向切片內追加數據,當超出容量後,自動分配更大的容量空間
	}

	fmt.Println(x)
}

輸出結果:

image-20210514230715956

channel 通道

image-20210519220142304

表達式

常用

package commlib

import "fmt"

//ExpressionTest
func ExpressionTest()  {

	//if
	fmt.Println("******IF******")
    
	x:=100
	y:=6

	if x > 0{
		fmt.Println("x+")
	}else if x < 0{
		fmt.Println("x-")
	}else {
		fmt.Println("0")
	}

	// swich
	fmt.Println("******swich******")
    
	switch {
		case x > 0:
			fmt.Println("100")
		case x<0:
			fmt.Println("250")
		default:
			fmt.Println("倆250")
	}

	// for
	fmt.Println("******for++******")
    
	for i:=0;i<5;i++ {
		fmt.Println(i)
	}
    
	fmt.Println("******for--******")
    
	for i:=5;i>1;i--{
		fmt.Println(i)
	}
    
	fmt.Println("******相當於while(x<10)******")
	
    for y<10{

		y++

		fmt.Println(y)
	}
	
    fmt.Println("******相當於while(true)******")
	
    for{
		fmt.Println(x)

		x = x-50

		if x == 0 {
			break
		}
	}
	
    fmt.Println("******返回索引和值******")
	
    arr:=[]int{1,2,3,4,5}

	for i,n := range arr{
		fmt.Println(i,":",n)
	}
}

執行結果:

image-20210514224453702

標籤

for 標籤

fmt.Println("給For 打標籤,應用 break | continue 跳出或者終止循環")

f1:for i:=0;i<4;i++{ //f1 標籤
    for j:=0;j<4;j++{
        if i==2{
            break f1  //此處結束的循環是f1 標籤所對應的i for 循環
        }
        fmt.Println(i,j)
    }
}

輸出結果:

image-20210515165154495

goto 跳躍

  • 跳躍到指定行,然後向下執行代碼
package api

import "fmt"

func GotoMethod()  {
	fmt.Println("請輸入姓名:")
	var name string
	fmt.Scanln(&name)

	if name == "Harris"{
		goto SVIP
	}else if name=="Dongjie"{
		goto VIP
	}

	fmt.Println("預約...")
VIP:
	fmt.Println("等號...")
SVIP:
	fmt.Println("治療...")
}

image-20210517214916383image-20210517214945026image-20210517215011356

字符串格式化

package api

import "fmt"

func StringFormatMenthod()  {
	var name,address,action string

	fmt.Println("請輸入姓名")

	fmt.Scanln(&name)

	fmt.Println("請輸入地址")

	fmt.Scanln(&address)

	fmt.Println("請輸入行爲")

	fmt.Scanln(&action)

	result := fmt.Sprintf("我叫%s,我正在%s旁邊%s",name,address,action)

	fmt.Println(result)
}

輸出:

image-20210517220631093

運算符

位運算符

進制轉換:

例如:101000 -> 2*5 + 2**3 -> 32 + 8 = 40

1. 按位進行與運算(全爲1,才得1)

r1 := 5 & 99
5  -> 0000101
99 -> 1100011
      0000001 -> 1

2. 按位進行或運算(只要有1,就得1)

r2 := 5 | 99
5  -> 0000101
99 -> 1100011
      1100111 -> 2*6 +2*5 +2*2 + 2*1 + 2*0 -> 64+32+4+2+1 = 103

3. 按位進行異或運算(上下不同,就得1)

r3 := 5 ^ 99
5  -> 0000101
99 -> 1100011
      1100110 -> 2*6 +2*5 +2*2 + 2*1 -> 64+32+4+2 = 102

4. 按鈕進行左移運算

r4 := 5 << 2
5  -> 0000101 -> 101 //前面的0可以省略
所以:101 左移之後 後面補0 -> 10100 -> 2*4+2*2 -> 16+4 = 20

5. 按位進行右移運算

r5 := 5 >> 1
5  -> 0000101 -> 101 //前面的0可以省略
所以:101 右移之後 10 右移1位,後面咬去1位, -> 10 -> 2*1 = 2

image-20210517230842863

補充:

  • 十進制轉二進制

    十進制 二進制(逢二進一)
    0 0
    1 1
    2 10
    3 11
    4 100
    5 101
    6 110
    7 111
    8 1000
    9 1001
    10 1010

函數

package commlib

import (
	"errors"
	"fmt"
)

// 函數可以定義多個返回值,甚至對其命名
func FunctionTest(a, b int) (int, error) {
	if b == 0 {
		return 0, errors.New("FunctionTest")
	}
	return a / b, nil
}

func FunctionTest2() {
	a, b := 1, 0 //定義多個變量

	c, err := FunctionTest(a, b) //接受多個返回值

	fmt.Println(c, err)
}

//函數是第一類型,可以作爲參數或者返回值
func FunctionTest3(x int)func()  {//返回函數類型
	return func() {//匿名函數
		fmt.Println("返回參數爲函數",x)//閉包
	}
}

func FunctionTest4()  {
	x:=100

	f:=FunctionTest3(x)//返回函數

	f()//執行函數
}

//通過關鍵字 defer 來修飾動作標識最後執行
func FunctionTest5(a,b int)  {

	defer fmt.Println("延遲執行的動作")

	fmt.Println("正在執行的動作")

	fmt.Println(a+b)
}

func FunctionTest6()  {
	x,y := 10,0

	FunctionTest5(x,y)
}

執行:

fmt.Println("執行:FunctionTest2")//函數可以定義多個返回值,甚至對其命名
commlib.FunctionTest2()
fmt.Println("執行:FunctionTest4")//函數是第一類型,可以作爲參數或者返回值
commlib.FunctionTest4()
fmt.Println("執行:FunctionTest6")//通過關鍵字 defer 來修飾動作標識最後執行
commlib.FunctionTest6()

執行結果:

image-20210514224544469

常見問題

  1. go.mod file not found in current directory or any parent directory; see 'go help modules'

    問題是go環境的問題:執行go env -w GO111MODULE=auto

  2. 修改配置:運行種類和包位置 可以解決運行只侷限在某個文件的問題

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章