1. 程式人生 > 其它 >Go 程式碼記錄(一)

Go 程式碼記錄(一)

1、hello world!

// 同一個目錄下面不能有個多 package main
package main

// 導包
import "fmt"

// 程式入口
func main() {
	fmt.Println("Hello world")
}

2、HTTP檔案伺服器

// 標記當前檔案為 main 包,main 包也是 Go 程式的入口包
package main

// 匯入 net/http 包,這個包的作用是 HTTP 的基礎封裝和訪問
import (
	"net/http"
)

/**
HTTP檔案伺服器
*/
// 程式執行的入口函式 main()
func main() {

	// 使用 http.FileServer 檔案伺服器將當前目錄作為根目錄(/目錄)的處理器,訪問根目錄,就會進入當前目錄
	http.Handle("/", http.FileServer(http.Dir(".")))
	// 預設的 HTTP 服務偵聽在本機 8080 埠
	http.ListenAndServe(":8080", nil)
}

// 在瀏覽器裡輸入http://127.0.0.1:8080即可瀏覽檔案,這些檔案正是當前目錄在HTTP伺服器上的對映目錄。

3、併發程式設計

// 同一個目錄下面不能有個多 package main
package main

// 匯入格式化(fmt)、隨機數(math/rand)、時間(time)包參與編譯
import (
	"fmt"
	"math/rand"
	"time"
)

// 生產資料的函式,傳入一個標記型別的字串及一個只能寫入的通道
// 資料生產者
func producer(header string, channel chan<- string) {
	// for{} 構成一個無限迴圈
	// 無限迴圈,不停地生產資料
	for {
		// 使用 rand.Int31() 生成一個隨機數,使用 fmt.Sprintf() 函式將 header 和隨機數格式化為字串
		// 將隨機數和字串格式化為字串傳送給通道
		channel <- fmt.Sprintf("%s: %v", header, rand.Int31())
		// 使用 time.Sleep() 函式暫停 1 秒再執行這個函式。如果在 goroutine 中執行時,暫停不會影響其他 goroutine 的執行
		// 等待1秒
		time.Sleep(time.Second)
	}
}

// 消費資料的函式,傳入一個只能寫入的通道
// 資料消費者
func customer(channel <-chan string) {
	// 不停的獲取資料
	for {
		// 從通道中獲取資料,此處會阻塞直到通道中返回資料
		message := <-channel
		// 列印資料
		fmt.Println(message)
	}
}

// 程式的入口函式,總是在程式開始時執行
func main() {

	// 建立一個字串型別的通道
	channel := make(chan string)
	// 併發執行一個生產者函式,兩行分別建立了這個函式搭配不同引數的兩個 goroutine
	// 建立producer()函式的併發goroutine
	go producer("cat", channel)
	go producer("dog", channel)
	// 執行消費者函式通過通道進行資料消費
	// 資料消費函式
	customer(channel)
}

/**
整段程式碼中,沒有執行緒建立,沒有執行緒池也沒有加鎖,僅僅通過關鍵字 go 實現 goroutine,和通道實現資料交換。

編譯成exe檔案:go build go-test/test3/concurrent.go
*/

4、計算器

add.go

package simplemath

// 加法
func Add(a int, b int) int{
	return a + b
}

sqrt.go

package simplemath

import "math"

// 平方根
func Sqrt(i int) int{
	v := math.Sqrt(float64(i))
	return int(v)
}

main.go

package main

// 引入其他包
import (
	"fmt"
	"go-test/simplemath"
	"os"
	"strconv"
)
// 定義一個用於列印程式使用指南的函式
var Usage = func(){
	fmt.Println("USAGE:calc command [arguments] ...")
	fmt.Println("\nThe commands are:\n\tadd\t計算兩個數值相加\n\tsqrt\t計算一個非負數的平方根")
}

// 程式入口函式
func main(){
	/*
	 * 用於獲取命令列引數,注意程式名本身是第一個引數,
	 * 比如 calc add 1 2 這條指令,第一個引數是 calc
	 */
	// := 宣告並初始化變數,不需要通過 var 宣告該變數
	args := os.Args
	// 除程式名本身外,至少需要傳入兩個其他引數,否則退出
	if args == nil || len(args) < 3{
		Usage()
		return
	}
	// 第二個引數表示計算方法
	switch args[1]{
		// 加法
		case "add":
			// 至少需要4個引數
			if len(args) != 4{
				fmt.Println("USAGE: calc add <integer1><integer2>")
				return
			}
			// 獲取待相加的型別,並將型別轉換為整型
			v1, err1 := strconv.Atoi(args[2])
			v2, err2 := strconv.Atoi(args[3])
			// 獲取引數出錯,則退出
			if err1	!= nil || err2 != nil{
				fmt.Println("USAGE: calc add <integer1><integer2>")
				return
			}
			// 從 simplemath 包引入 Add 方法
			ret := simplemath.Add(v1, v2)
			fmt.Println("Result: ", ret)
		// 求方根
		case "sqrt":
			if len(args) != 3{
				fmt.Println("USAGE: calc sqrt <integer>")
				return
			}
			v, err := strconv.Atoi(args[2])
			if err != nil{
				fmt.Println("USAGE: calc sqrt <integer>")
				return
			}
			ret := simplemath.Sqrt(v)
			fmt.Println("Result: ", ret)

		default:
			Usage()
	}
}