透過示例學習-Go-語言-2023-二十八-

绝不原创的飞龙發表於2024-10-19

透過示例學習 Go 語言 2023(二十八)

在 Go(Golang)中逐行讀取大檔案

來源:golangbyexample.com/read-large-file-line-by-line-go/

當涉及到讀取大檔案時,顯然我們不想將整個檔案載入到記憶體中。Golang 中的 bufio 包在讀取大檔案時提供了幫助。假設我們有一個名為 sample.txt 的檔案,其內容如下

This is an example
to show how
to read file 
line by line.

這是程式:

package main
import (
    "bufio"
    "fmt"
    "log"
    "os"
)
func main(){
    LinebyLineScan()
}
func LinebyLineScan() {
    file, err := os.Open("./sample.txt")
    if err != nil {
        log.Fatal(err)
    }
    defer file.Close()
    scanner := bufio.NewScanner(file)
    for scanner.Scan() {
        fmt.Println(scanner.Text())
    }
    if err := scanner.Err(); err != nil {
        log.Fatal(err)
    }
}

輸出:

This is an example
to show how 
to read file 
line by line.

不過請注意,bufio.Scanner 的最大緩衝區大小為 641024 位元組,這意味著如果你的檔案中有任何一行超過 641024 的大小,那麼它將會報錯

bufio.Scanner: token too long
  • 檔案* go* 大檔案* 逐行讀取* 逐行

在 Go(Golang)中逐字讀取大型檔案

來源:golangbyexample.com/read-large-file-word-by-word-go/

處理大型檔案時,顯然我們不想將整個檔案載入到記憶體中。在 Golang 中,bufio 包在讀取大型檔案時提供了幫助。假設我們有一個名為 sample.txt 的檔案,內容如下:

This is an example
to show how
to read file
word by word.

逐字掃描

package main
import (
    "bufio"
    "fmt"
    "log"
    "os"
)
func main() {
    WordbyWordScan()
}
func WordbyWordScan() {
    file, err := os.Open("./scanner/sample.txt")
    if err != nil {
        log.Fatal(err)
    }
    defer file.Close()
    scanner := bufio.NewScanner(file)
    scanner.Split(bufio.ScanWords)
    for scanner.Scan() {
        fmt.Println(scanner.Text())
    }
    if err := scanner.Err(); err != nil {
        log.Fatal(err)
    }
}

輸出:

This
is
an
example
to
show
how
to
read
file
line
by
line
and
word
by
word.

請注意,在上面的程式中,我們設定了scanner.Split(bufio.ScanWords),這有助於我們逐字讀取檔案。不過需要注意的是,bufio.Scanner 的最大緩衝區大小為 641024 位元組,這意味著如果你的檔案中有任何一行超過 641024 的大小,將會出現錯誤。

bufio.Scanner: token too long

在 Go(Golang)中讀取 cookie http

來源:golangbyexample.com/read-cookie-http-golang/

目錄

  • 概述

  • 程式

概述

net/http Request 結構體提供了一種方便的方法,可以根據名稱讀取特定 cookie。以下是該方法的簽名。golang.org/pkg/net/http/#Request.Cookie

func (r *Request) Cookie(name string) (*Cookie, error)

要列印所有 cookies,我們可以遍歷http.Request結構體的Cookies方法。我們可以為此使用 range 關鍵字。

for _, c := range r.Cookies() {
     fmt.Println(c)
}

這兩個函式將返回Cookie結構體的例項。在 golang 中,cookie 表示如下。

golang.org/src/net/http/cookie.go

type Cookie struct {
	Name  string
	Value string

	Path       string    // optional
	Domain     string    // optional
	Expires    time.Time // optional
	RawExpires string    // for reading cookies only

	// MaxAge=0 means no 'Max-Age' attribute specified.
	// MaxAge<0 means delete cookie now, equivalently 'Max-Age: 0'
	// MaxAge>0 means Max-Age attribute present and given in seconds
	MaxAge   int
	Secure   bool
	HttpOnly bool
	SameSite SameSite
	Raw      string
	Unparsed []string // Raw text of unparsed attribute-value pairs
}

有關上述 cookie 中每個欄位的詳細資訊,請參見tools.ietf.org/html/rfc6265

程式

以下是相同程式,展示CookieCookies方法的http.Request結構體

package main

import (
	"fmt"
	"log"
	"net/http"
)

func main() {
	docHandler := http.HandlerFunc(docHandler)
	http.Handle("/doc", docHandler)

	http.ListenAndServe(":8080", nil)
}

func docHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Println("Cookies in API Call:")

	tokenCookie, err := r.Cookie("token")
	if err != nil {
		log.Fatalf("Error occured while reading cookie")
	}
	fmt.Println("\nPrinting cookie with name as token")
	fmt.Println(tokenCookie)

	fmt.Println("\nPrinting all cookies")
	for _, c := range r.Cookies() {
		fmt.Println(c)
	}
	fmt.Println()
	w.WriteHeader(200)
	w.Write([]byte("Doc Get Successful"))
	return
}

執行上面的程式並進行以下 curl 呼叫

curl -X GET localhost:8080/doc --cookie "id=abcd; token=some_token"

curl 呼叫傳遞了兩個 cookie 名稱-值對

  • id=abcd

  • token=some_token

它將給出以下輸出

Cookies in API Call:

Printing cookie with name as "token"
token=some_token

Printing all cookies
id=abcd
token=some_token

這就是我們如何列印名為“token”的特定 cookie

tokenCookie, err := r.Cookie("token")

它的輸出如所見

token=some_token

這就是我們如何列印所有的 cookie

for _, c := range r.Cookies() {
     fmt.Println(c)
}

它輸出我們在 curl 呼叫中傳送的 cookie 名稱-值對

id=abcd
token=some_token

這就是關於 golang 中 cookies 的所有內容。希望你喜歡這個教程。請在評論中分享反饋。

此外,請檢視我們的 Golang 高階教程系列 – Golang 高階教程

  • cookie* go* golang*

在 Go (Golang) 中從通道讀取/接收所有值

來源:golangbyexample.com/receive-all-values-channel-golang/

目錄

  • 概述**

  • 程式碼

概述

對於範圍迴圈,可以用來接收來自通道的資料,直到它被關閉。請注意,for-range 迴圈會持續接收通道中的資料,唯一退出範圍迴圈的方式是關閉通道。

讓我們來看一個程式以理解這一點。

程式碼

package main

import (
	"fmt"
	"time"
)

func main() {
	ch := make(chan int)
	ch <- 2
	ch <- 2
	ch <- 2
	close(ch)
	sum(ch)
	time.Sleep(time.Second * 1)
}

func sum(ch chan int) {
	sum := 0
	for val := range ch {
		sum += val
	}
	fmt.Printf("Sum: %d\n", sum)
}

輸出

Sum: 6

在上面的程式中,我們建立了一個通道。在主函式中,傳送了三個值到通道,然後關閉了通道。接著我們呼叫了 sum 函式,並將通道傳遞給該函式。在 sum 函式中,我們對通道進行了 for-range 迴圈。在遍歷完通道中的所有值後,由於通道已關閉,for-range 迴圈將退出。

現在腦海中浮現的問題是,如果在主函式中不關閉通道會發生什麼。嘗試註釋掉關閉通道的那一行。然後執行程式。它也會輸出死鎖,因為 for-range 迴圈在 sum 函式中永遠不會結束。

fatal error: all goroutines are asleep - deadlock!

如果我們需要在通道關閉前接收固定數量的值,可以使用 for 迴圈。讓我們看一個例子。

package main

import (
    "fmt"
    "time"
)

func main() {
    ch := make(chan int, 3)
    ch <- 2
    ch <- 2
    ch <- 2
    close(ch)
    sum(ch)
    time.Sleep(time.Second * 1)
}

func sum(ch chan int) {
    sum := 0
    for i := 0; i < 2; i++ {
        val := <-ch
        sum += val
    }
    fmt.Printf("Sum: %d\n", sum)
}

輸出

Sum: 4

在上面的程式中,我們有一個容量為 3 的緩衝通道。在主函式中,我們向通道傳送了 3 個值。在 sum 函式中,我們有一個 for 迴圈,迭代兩次,只從通道中接收兩個值並進行相加。只有在我們想從通道中接收固定數量的值時,for 迴圈才有用。

在 Go(Golang)中接收或獲取來自 goroutine 的多個返回值

來源:golangbyexample.com/receive-multiple-return-value-goroutine-golang/

通道可以用於從 goroutine 中獲取返回值。通道提供了 goroutine 之間的同步和通訊。你可以在 goroutine 中將返回值傳送到通道,然後在主函式中收集該值。

為了接收多個值,我們可以建立一個自定義結構體型別,其中包含兩個返回值的欄位,然後建立該型別的通道。

讓我們看看一個程式。

package main

import (
	"fmt"
	"time"
)

type result struct {
	sumValue      int
	multiplyValue int
}

func main() {
	resultChan := make(chan result, 1)
	sumAndMultiply(2, 3, resultChan)

	res := <-resultChan
	fmt.Printf("Sum Value: %d\n", res.sumValue)
	fmt.Printf("Multiply Value: %d\n", res.multiplyValue)
	close(resultChan)

}

func sumAndMultiply(a, b int, resultChan chan result) {
	sumValue := a + b
	multiplyValue := a * b
	res := result{sumValue: sumValue, multiplyValue: multiplyValue}
	time.Sleep(time.Second * 2)
	resultChan <- res
	return
}

輸出

Sum Value: 5
Multiply Value: 6

在上述程式中,我們建立了一個名為result的結構體,它有兩個欄位。

  • sumValue

  • multiplyValue

我們建立了一個變數resultChan,它是一個長度為 1 的通道,儲存result結構體型別的值。我們將這個通道傳遞給sumAndMultiply函式。sumAndMultiply函式將結果結構體推送到resultChan

res := result{sumValue: sumValue, multiplyValue: multiplyValue}
resultChan <- res

然後在主函式中,我們正在等待通道以收集結果。

res := <-resultChan

這行程式碼將等待,直到一個值被推送到resultChan通道。

從 Go(Golang)中的 goroutine 接收或獲取返回值

來源:golangbyexample.com/return-value-goroutine-go/

通道可以用來從 goroutine 獲取返回值。通道提供了 goroutine 之間的同步和通訊。你可以在 goroutine 中透過通道傳送返回值,然後在 main 函式中收集該值。

讓我們看看一個程式。

package main

import "fmt"

func main() {
	result := make(chan int, 1)
	go sum(2, 3, result)

	value := <-result
	fmt.Printf("Value: %d\n", value)
	close(result)

}

func sum(a, b int, result chan int) {
	sumValue := a + b
	result <- sumValue
	return
}

輸出

Value: 5

在上面的程式中,我們建立了一個變數result,這是一個長度為 1、存放int型別值的通道。我們將這個通道傳遞給sum函式。sum函式將sumValue推送到result通道,如此操作。

result <- sumValue

在 main 函式中,我們在等待result通道以收集結果。

value := <-result

這一行將等待一個值被推送到result通道。如上所示,sumValue將透過sum函式推送到result通道。

為了說明這一行確實會等待,讓我們在 sum 函式中設定一個超時,它實際上將sumValue推送到result通道。

package main

import (
	"fmt"
	"time"
)

func main() {
	result := make(chan int, 1)
	go sum(2, 3, result)

	value := <-result
	fmt.Printf("Value: %d\n", value)
	close(result)

}

func sum(a, b int, result chan int) {
	sumValue := a + b
	time.Sleep(time.Second * 2)
	result <- sumValue
	return
}

輸出

Value: 5

程式輸出相同,這證明main函式等待sumValue被推送到result通道。一旦從result通道接收到值,它就會列印出來。

在 Go 語言中在不同函式中恢復 panic

來源:golangbyexample.com/recover-panic-different-function-go/

目錄

  • 概述

  • 程式

概述

如果defer函式和recover函式沒有從引發恐慌的函式中被呼叫,那麼在這種情況下panic也可以在被呼叫的函式中恢復。實際上,panic 可以在呼叫棧的後續鏈中恢復,讓我們來看一個例子。

程式

package main

import "fmt"

func main() {
    a := []string{"a", "b"}
    checkAndPrintWithRecover(a, 2)
    fmt.Println("Exiting normally")
}

func checkAndPrintWithRecover(a []string, index int) {
    defer handleOutOfBounds()
    checkAndPrint(a, 2)
}

func checkAndPrint(a []string, index int) {
    if index > (len(a) - 1) {
        panic("Out of bound access for slice")
    }
    fmt.Println(a[index])
}

func handleOutOfBounds() {
    if r := recover(); r != nil {
        fmt.Println("Recovering from panic:", r)
    }
}

輸出

Recovering from panic: Out of bound access for slice
Exiting normally

在上面的程式中,我們有一個函式checkAndPrint,它檢查並列印傳入引數的索引處的切片元素。如果傳入的索引大於陣列的長度,程式將會引發 panic。

我們還有另一個函式checkAndPrintWithRecover,它包含對

我們還有另一個函式checkAndPrintWithRecover,它包含對

  • 帶有recoverdefer函式,名為handleOutOfBounds

  • 呼叫checkAndPrint函式

所以我們在函式checkAndPrintWithRecover的開頭有一個名為handleOutIfBounds的延遲函式。這個函式包含如下的 recover 函式呼叫。

if r := recover(); r != nil {
    fmt.Println("Recovering from panic:", r)
}

checkAndPrint函式引發了 panic,但沒有 recover 函式,相反,recover 的呼叫在checkAndPrintWithRecover函式中。我們將索引 2 傳遞給checkAndPrint函式,這個索引超出了邊界。因此checkAndPrint引發了 panic,但程式仍然能夠從 panic 中恢復,正如輸出所示。這是因為 panic 可以在被呼叫的函式中恢復,並且在呼叫鏈中也可以恢復。

在 Go (Golang)中恢復二叉搜尋樹程式

來源:golangbyexample.com/recover-binary-search-tree-golang/

目錄

  • 概述

  • 程式

概述

給定一個二叉搜尋樹的根節點。兩個二叉搜尋樹的節點已被交換。我們需要修復二叉樹並恢復原始結構。

程式

下面是相應的程式

package main

import "fmt"

type TreeNode struct {
	Val   int
	Left  *TreeNode
	Right *TreeNode
}

func recoverTree(root *TreeNode) {
	var prev *TreeNode
	var first *TreeNode
	var mid *TreeNode
	var last *TreeNode

	recoverTreeUtil(root, &prev, &first, &mid, &last)

	if first != nil && last != nil {
		first.Val, last.Val = last.Val, first.Val
	} else if first != nil && mid != nil {
		first.Val, mid.Val = mid.Val, first.Val
	}
}

func recoverTreeUtil(root *TreeNode, prev, first, mid, last **TreeNode) {
	if root == nil {
		return
	}

	recoverTreeUtil(root.Left, prev, first, mid, last)

	if *prev == nil {
		*prev = root
	} else if *first == nil && (*prev).Val > root.Val {
		*first = *prev
		*mid = root
	} else if (*prev).Val > root.Val {
		*last = root
	}

	*prev = root

	recoverTreeUtil(root.Right, prev, first, mid, last)
}

func main() {
	root := TreeNode{Val: 2}
	root.Left = &TreeNode{Val: 3}
	root.Right = &TreeNode{Val: 1}

	recoverTree(&root)
	fmt.Println(root.Val)
	fmt.Println(root.Left.Val)
	fmt.Println(root.Right.Val)

}

輸出

2
1
3

注意: 請檢視我們的 Golang 高階教程。本系列教程內容詳盡,我們儘量涵蓋所有概念和示例。本教程適合希望獲得專業知識和紮實理解 Golang 的人 – Golang 高階教程

如果你對了解所有設計模式如何在 Golang 中實現感興趣的話。如果是,那麼這篇文章就是為你準備的 – 所有設計模式 Golang

此外,請檢視我們的系統設計教程系列 – 系統設計教程系列

Go(Golang)中的recover函式返回值

來源:golangbyexample.com/recover-return-value-golang/

目錄

  • 概述

  • 示例

概述

recover函式返回傳遞給panic函式的值。因此,檢查recover函式的返回值是一種良好實踐。如果返回值非空,則表示沒有發生panic,且recover函式沒有因panic被呼叫。

示例

讓我們看一個程式以充分理解它

package main

import "fmt"

func main() {

	a := []string{"a", "b"}
	checkAndPrint(a, 2)
	fmt.Println("Exiting normally")
}

func checkAndPrint(a []string, index int) {
	defer handleOutOfBounds()
	if index > (len(a) - 1) {
		panic("Out of bound access for slice")
	}
	fmt.Println(a[index])
}

func handleOutOfBounds() {
	if r := recover(); r != nil {
		fmt.Println("Recovering from panic:", r)
	}
}

輸出

Recovering from panic: Out of bound access for slice
Exiting normally

在上面的程式中,我們有一個函式checkAndPrint,它檢查並列印傳遞給引數的索引處的切片元素。如果傳遞的索引大於陣列的長度,則程式將發生panic。我們在函式checkAndPrint的開始處新增了一個名為handleOutIfBoundsdefer函式。此函式包含對recover函式的呼叫,如下所示。

if r := recover(); r != nil {
    fmt.Println("Recovering from panic:", r)
}

recover函式將捕獲panic,我們也可以列印來自panic的訊息。

Recovering from panic: Out of bound access for slice

recover函式之後,程式繼續執行,控制權返回到呼叫的函式,這裡是main。這就是我們得到輸出的原因。

Exiting normally

recover函式返回傳遞給panic函式的值。這就是我們在defer函式handleOutofBounds中有下面程式碼的原因。

if r := recover(); r != nil 

在這裡,如果r為 nil,則表示沒有發生panic。因此,如果沒有panic,則對recover的呼叫將返回 nil。

在 Go (Golang)中的協程中恢復 panic

來源:golangbyexample.com/recover-panic-goroutine-go/

目錄

  • 概述

  • 在相同協程中作為 panic 的 recover 函式

  • 在不同協程中的 recover 函式作為 panic

概述

恢復協程中恐慌的情況有兩種。

  • 在相同協程中的 recover 函式作為panic**

  • 在不同協程中的 recover 函式作為panic**

在第一種情況下,它將從 panic 中恢復。但需要注意的一個重要點是,recover 函式只能恢復在同一協程中發生的 panic。如果 panic 發生在不同協程中,而 recover 也在不同協程中,則無法恢復。

讓我們看看兩個例子的情況。

在相同協程中的 recover 函式作為 panic

package main

import "fmt"

func main() {
    a := []string{"a", "b"}
    go checkAndPrintWithRecover(a, 2)
    fmt.Println("Exiting normally")
}

func checkAndPrintWithRecover(a []string, index int) {
    defer handleOutOfBounds()
    checkAndPrint(a, 2)
}

func checkAndPrint(a []string, index int) {
    if index > (len(a) - 1) {
        panic("Out of bound access for slice")
    }
    fmt.Println(a[index])
}

func handleOutOfBounds() {
    if r := recover(); r != nil {
        fmt.Println("Recovering from panic:", r)
    }
}

輸出

Exiting normally
Recovering from panic: Out of bound access for slice

在上述程式中,recoverpanic位於同一協程中,因此能夠從 panic 中恢復,正如從輸出中所見。

在不同協程中的 recover 函式作為 panic

如前所述,在這種情況下無法從 panic 中恢復。

package main
import "fmt"
func main() {
    a := []string{"a", "b"}
    checkAndPrintWithRecover(a, 2)
    fmt.Println("Exiting normally")
}
func checkAndPrintWithRecover(a []string, index int) {
    defer handleOutOfBounds()
    go checkAndPrint(a, 2)
}
func checkAndPrint(a []string, index int) {
    if index > (len(a) - 1) {
        panic("Out of bound access for slice")
    }
    fmt.Println(a[index])
}
func handleOutOfBounds() {
    if r := recover(); r != nil {
        fmt.Println("Recovering from panic:", r)
    }
}

輸出

Exiting normally
panic: Out of bound access for slice

goroutine 18 [running]:
main.checkAndPrint(0xc0000a6020, 0x2, 0x2, 0x2)
        /Users/slohia/go/src/github.com/golang-examples/articles/tutorial/panicRecover/goroutine/main.go:19 +0xe2
created by main.checkAndPrintWithRecover
        /Users/slohia/go/src/github.com/golang-examples/articles/tutorial/panicRecover/goroutine/main.go:14 +0x82
exit status 2

在上述程式中,我們在協程中有checkAndPrint,它在該協程中引發了panicrecover函式在呼叫協程中。正如您從輸出中看到的,它並沒有停止panic,因此您看到了一些資訊。

Go(Golang)中的餘數或模運算

來源:golangbyexample.com/remainder-modulus-go-golang/

目錄

  • 概述

  • % 運算子

    • 程式碼
  • 浮點數的 Mod 函式

    • 程式碼
  • IEEE 754 餘數

    • 程式碼

概述

在本教程中,我們將學習關於

  • % 運算子 – 適用於獲取整數的餘數

  • Mod 函式 – 也可以用於獲取浮點數的餘數

  • 餘數函式 – 可用於獲取 IEEE 754 餘數

% 運算子

Golang 有一個模運算子 (‘ %’),可用於獲取兩個整數相除後的餘數。我們來看一個示例程式。

程式碼

package main

import (
    "fmt"
)

func main() {
    res := 4 % 2
    fmt.Println(res)

    res = 5 % 2
    fmt.Println(res)

    res = 8 % 3
    fmt.Println(res)
}

輸出:

0
1
2

浮點數的 Mod 函式

% 函式不適用於浮點數。要獲取兩個浮點數相除的餘數,我們可以使用 math 包提供的 Mod 函式。以下是該函式的簽名。它接受兩個浮點數並返回一個浮點數,返回 x/y 的浮點餘數,輸出將採用 x 的符號。

func Mod(x, y float64) float64

Mod 函式的一些特殊情況是

  • Mod(±Inf, y) = NaN

  • Mod(NaN, y) = NaN

  • Mod(x, 0) = NaN

  • Mod(x, ±Inf) = x

  • Mod(x, NaN) = NaN

程式碼

package main

import (
    "fmt"
    "math"
)

func main() {
    res := math.Mod(4, 2)
    fmt.Println(res)

    res = math.Mod(4.2, 2)
    fmt.Println(res)

    res = math.Mod(5, 2)
    fmt.Println(res)

    res = math.Mod(-5, 2)
    fmt.Println(res)
}

輸出

0
0.20000000000000018
1
-1

IEEE 754 餘數

Go 的 math 包提供了一個 Remainder 方法,可以用來獲取兩個數的 IEEE 754 餘數,其中一個作為分子,另一個作為分母。

你可以在這裡閱讀更多關於我們為什麼需要 IEEE 754 餘數 的資訊 – stackoverflow.com/questions/26671975/why-do-we-need-ieee-754-remainder

以下是該函式的簽名。它接受兩個 float64 型別的數字並返回一個餘數,這也是一個 IEEE 754 float64 餘數

func Remainder(x, y float64) float64

餘數函式的一些特殊情況是

  • Remainder(±Inf, y) = NaN

  • Remainder(NaN, y) = NaN

  • Remainder(x, 0) = NaN

  • Remainder(x, ±Inf) = x

  • Remainder(x, NaN) = NaN

程式碼

package main

import (
    "fmt"
    "math"
)

func main() {
    res := math.Remainder(4, 2)
    fmt.Println(res)

    res = math.Remainder(5, 2)
    fmt.Println(res)

    res = math.Remainder(5.5, 2)
    fmt.Println(res)

    res = math.Remainder(5.5, 1.5)
    fmt.Println(res)
}

輸出

0
1
-0.5
-0.5

從 Go 模組中移除依賴項(Golang)

來源:golangbyexample.com/remove-dependency-golang/

目錄

  • 概述

  • 示例

概述

要移除一個模組依賴項,我們需要做以下兩件事

  • 從模組的原始檔中移除該依賴項的引用

  • 執行go mod tidy命令。移除go.mod檔案中不需要的所有依賴項。

示例

假設我們有一個模組,匯入名為“learn”的模組,包含以下go.mod檔案和learn.go檔案。

go.mod

module learn

go 1.14

require github.com/pborman/uuid v1.2.1

learn.go

package main

import (
	"fmt"
	"strings"

	"github.com/pborman/uuid"
)

func main() {
	uuidWithHyphen := uuid.NewRandom()
	uuid := strings.Replace(uuidWithHyphen.String(), "-", "", -1)
	fmt.Println(uuid)
}

注意我們在learn.go中匯入了該依賴項,並且這個依賴項也被新增到go.mod檔案中

"github.com/pborman/uuid"

現在讓我們嘗試從上述模組完全移除這個依賴項。命令go mod tidy將從go.mod檔案中移除該依賴項,如果它在原始檔中不需要。為了說明這一點,讓我們刪除之前建立的learn.go檔案。現在執行命令

go mod tidy -v

它將給出以下輸出

unused github.com/pborman/uuid

現在檢查go.mod檔案的內容。它將如下所示

module learn

go 1.14

require github.com/pborman/uuid v1.2.1

該行將被移除,因為在任何原始檔中都不需要它。此外,github.com/pborman/uuid及其依賴項的所有條目也將從go.sum檔案中移除。

在 Go(Golang)中原地移除陣列中的給定值的所有出現

來源:golangbyexample.com/remove-element-golang/

目錄

  • 概述

  • 程式

概述

給定一個整數陣列和一個目標元素。從陣列中移除所有該目標元素的出現。刪除必須在原地進行。

Input: [1, 4, 2, 5, 4]
Target: 4
Output: [1, 2, 5]

Input: [1, 2, 3]
Target:3
Output: [1, 2]

程式

這裡是相應的程式。

package main

import (
	"fmt"
)

func removeElement(nums []int, val int) []int {
	lenNums := len(nums)

	k := 0

	for i := 0; i < lenNums; {
		if nums[i] != val {
			nums[k] = nums[i]
			k++
		}
		i++
	}
	return nums[0:k]
}

func main() {
	output := removeElement([]int{1, 4, 2, 5, 4}, 4)
	fmt.Println(output)

	output = removeElement([]int{1, 2, 3}, 3)
	fmt.Println(output)
}

輸出

[1 2 5]
[1 2]

注意: 請檢視我們的 Golang 高階教程。本系列的教程內容詳盡,我們嘗試用例項覆蓋所有概念。本教程適合那些希望獲得專業知識和對 Golang 有深入理解的人 - Golang 高階教程

如果你有興趣瞭解所有設計模式如何在 Golang 中實現。如果是的話,這篇文章適合你 - 所有設計模式 Golang

在 Go (Golang)中去除浮點數的小數點

來源:golangbyexample.com/remove-decimal-float-go/

目錄

  • 概述

  • 程式碼:

概述

math包提供了一個Trunc方法,可用於移除浮點數的小數點並將其轉換為整數

以下是該函式的簽名。它接受一個浮點數作為輸入,並返回一個浮點數。

func Trunc(x float64) float64\

程式碼:

package main

import (
    "fmt"
    "math"
)

func main() {
    res := math.Trunc(1.6)
    fmt.Println(res)

    res = math.Trunc(-1.6)
    fmt.Println(res)

    res = math.Trunc(1)
    fmt.Println(res)
}

輸出:

1
-1
1

在 Go(Golang)中從已排序的陣列中移除重複項

來源:golangbyexample.com/remove-duplicates-sorted-array-golang/

目錄

  • 概述

  • 程式

概述

目標是從一個已排序的陣列中移除重複項。

示例

Input: [1, 1, 1, 2]
Output: [1, 2]

Input: [1, 2, 3, 3]
Output: [1, 2, 3]

程式

以下是相同的程式

package main

import "fmt"

func main() {
	input := []int{1, 1, 1, 2}
	output := removeDuplicates(input)
	fmt.Println(output)

	input = []int{1, 2, 3, 3}
	output = removeDuplicates(input)
	fmt.Println(output)
}

func removeDuplicates(nums []int) []int {
	lenArray := len(nums)

	k := 0
	for i := 0; i < lenArray; {
		nums[k] = nums[i]
		k++
		for i+1 < lenArray && nums[i] == nums[i+1] {
			i++
		}
		i++
	}

	return nums[0:k]
}

輸出

[1 2]
[1 2 3]

注意:檢視我們的 Golang 高階教程。本系列教程內容詳盡,我們嘗試覆蓋所有概念並附有示例。本教程適合那些希望獲得專業知識和紮實理解 Golang 的人 - Golang 高階教程

如果你有興趣瞭解所有設計模式如何在 Golang 中實現。如果是的話,這篇文章適合你 - 所有設計模式 Golang

在 Go (Golang)中刪除連結串列元素的程式

來源:golangbyexample.com/remove-linked-list-elements-golang/

目錄

  • 概述

  • 程式

概述

給定一個連結串列和一個值,刪除連結串列中所有值等於給定值的節點。

示例 1

Input: [1, 2, 1, 3, 6], 1
Output: [2, 3, 6]

示例 2

Input: [2, 2, 3], 2
Output: [3]

程式

下面是相應的程式

package main

import "fmt"

type ListNode struct {
	Val  int
	Next *ListNode
}

type SingleList struct {
	Len  int
	Head *ListNode
}

func (s *SingleList) AddFront(num int) *ListNode {
	ele := &ListNode{
		Val: num,
	}
	if s.Head == nil {
		s.Head = ele
	} else {
		ele.Next = s.Head
		s.Head = ele
	}
	s.Len++
	return ele
}
func removeElements(head *ListNode, val int) *ListNode {
	var prev *ListNode

	curr := head

	for curr != nil {
		if curr.Val == val {
			if prev == nil {
				head = curr.Next
			} else {
				prev.Next = curr.Next
			}
		} else {
			prev = curr
		}
		curr = curr.Next

	}

	return head
}

func main() {
	first := initList()
	first.AddFront(6)
	first.AddFront(3)
	first.AddFront(1)
	first.AddFront(2)
	first.AddFront(1)

	result := removeElements(first.Head, 1)
	fmt.Println("Resultant First List")
	result.Traverse()

	first = initList()
	first.AddFront(3)
	first.AddFront(2)
	first.AddFront(2)

	fmt.Println("\nResultant Second List")
	result = removeElements(first.Head, 2)
	result.Traverse()

}

func initList() *SingleList {
	return &SingleList{}
}

func (l *ListNode) Traverse() {
	for l != nil {
		fmt.Println(l.Val)
		l = l.Next
	}
}

輸出

Resultant First List
2
3
6

Resultant Second List
3

注意: 檢視我們的 Golang 高階教程。該系列教程內容詳盡,我們努力涵蓋所有概念及示例。本教程適合希望獲得專業知識和深入理解 Golang 的學習者 – Golang 高階教程

如果你對理解如何在 Golang 中實現所有設計模式感興趣。如果是的話,這篇文章適合你 – 所有設計模式 Golang

另外,可以在這裡檢視我們的系統設計教程系列 – 系統設計教程系列

在 Go (Golang) 中刪除或去掉字串中的所有空白字元。

來源:golangbyexample.com/remove-all-white-spaces-string-golang/

strings.ReplaceAll 函式可以用來去掉 Golang 字串中的所有空白字元。以下是該函式的簽名:

func ReplaceAll(s, old, new string) string
  • s(第一個引數)是輸入字串。

  • old(第二個引數)是要被替換的字串,new(第三個引數)是替換後的字串。

有效程式碼:

package main

import (
    "fmt"
    "strings"
)

func main() {
    sample := " This is a sample string   "
    noSpaceString := strings.ReplaceAll(sample, " ", "")
    fmt.Println(noSpaceString)
}

輸出:

Thisisasamplestring
  • 所有* 修剪

在 Go (Golang)中重新命名檔案或資料夾

來源:golangbyexample.com/rename-file-folder-golang/

目錄

  • 概述

  • 程式碼

    • 重新命名檔案

    • 重新命名資料夾

概述

可以使用 os.Rename()函式來重新命名檔案或資料夾。下面是該函式的簽名。

func Rename(old, new string) error

oldnew也可以是完整路徑。如果oldnew路徑不在同一目錄中,則os.Rename()函式的行為與移動檔案或資料夾相同。

程式碼

重新命名檔案

下面是重新命名檔案的程式碼

package main

import (
    "log"
    "os"
)

func main() {
    //Create a file
    file, err := os.Create("temp.txt")
    if err != nil {
        log.Fatal(err)
    }
    defer file.Close()

    //Change permission so that it can be moved
    err = os.Chmod("temp.txt", 0777)
    if err != nil {
        log.Println(err)
    }

    err = os.Rename("temp.txt", "newTemp.txt")
    if err != nil {
        log.Fatal(err)
    }
}

輸出

首先,它將在當前工作目錄中建立一個名為 temp.txt 的檔案。然後它將其重新命名為 newTemp.txt。

重新命名資料夾

下面是重新命名資料夾的程式碼

package main

import (
    "log"
    "os"
)

func main() {
    //Create a directory
    err := os.Mkdir("temp", 0755)
    if err != nil {
        log.Fatal(err)
    }
    err = os.Rename("temp", "newTemp")
    if err != nil {
        log.Fatal(err)
    }
}

輸出:

首先,它將在當前工作目錄中建立一個名為 temp 的資料夾。然後它將其重新命名為 newTemp。

  • 檔案* 資料夾* go* golang* 重新命名*

在 Go (Golang) 中重複一個字串多次

來源:golangbyexample.com/repeat-string-golang/

目錄

  • 概述

  • 程式

概述

strings.Repeat 方法可用於在 Go (Golang) 中多次重複一個字串

這是 Go 字串包中該函式的連結

pkg.go.dev/strings#Repeat

這是該方法的簽名

func Repeat(s string, count int) string

第一個引數是原始字串,count 是字串需要重複的次數

程式

這是相同內容的程式

package main

import (
	"fmt"
	"strings"
)

func main() {
	copy := strings.Repeat("a", 2)
	fmt.Println(copy)

	copy = strings.Repeat("abc", 3)
	fmt.Println(copy)
}

輸出:

aa
abcabcabc

注意: 請檢視我們的 Golang 高階教程。本系列的教程內容詳盡,我們努力覆蓋所有概念及示例。本教程適合那些希望獲得專業知識和深入理解 Golang 的人 – Golang 高階教程

如果你有興趣瞭解所有設計模式如何在 Golang 中實現。如果是的話,這篇文章就是為你準備的 – 所有設計模式 Golang

在 Go (Golang) 中用另一個字元替換字串中的字元

來源:golangbyexample.com/replace-character-string-go/

目錄

  • 概述

  • 程式碼:

概述

在 GO 中,字串是 UTF-8 編碼的。GO 的 strings 包提供了一個 Replace 方法,可以用來在給定字串中將一個字元替換為另一個字元。它返回字串的副本。

以下是該函式的簽名。

  • 提供要被替換的字元作為 old

  • 提供你想替換的字元作為 new

  • n 表示替換的次數。如果 n 為 -1,則所有 old 的例項將被替換為 new

func Replace(s, old, new string, n int)

讓我們看看工作程式碼。

程式碼:

package main

import (
    "fmt"
    "strings"
)

func main() {
    //It will replaces 1 instance of a with 1
    res := strings.Replace("abcdabxyabr", "a", "1", 1)
    fmt.Println(res)

    //It will replace all instances of a with 1
    res = strings.Replace("abcdabxyabr", "a", "1", -1)
    fmt.Println(res)
}

輸出:

1bcdabxyabr
1bcd1bxy1br
```*


<!--yml

分類:未分類

日期:2024-10-13 06:12:57

-->

# 在 Go (Golang)中將一個子字串的所有例項替換為另一個

> 來源:[`golangbyexample.com/replace-all-instances-substring-go/`](https://golangbyexample.com/replace-all-instances-substring-go/)

目錄

+   概述

+   程式碼:

# **概述**

在 GO 中,字串是 UTF-8 編碼的。GO 的**strings**包提供了一個**ReplaceAll**方法,可以用來替換給定子字串的所有不重疊例項為一個新的子字串。它返回字串的副本。

下面是該函式的簽名。該函式將在字串**s**中替換所有不重疊的**old**例項為**new**。如果**old**為空,則它將在字串**s**中的每個有效的 UTF-8 位元組序列之間插入**new**。

```go
func ReplaceAll(s, old, new string) string

讓我們來看一下工作的程式碼

程式碼:

package main

import (
    "fmt"
    "strings"
)

func main() {
    res := strings.ReplaceAll("abcdabxyabr", "ab", "12")
    fmt.Println(res)

    res = strings.ReplaceAll("abcdabxyabr", "", "12")
    fmt.Println(res)
}

輸出

12cd12xy12r
12a12b12c12d12a12b12x12y12a12b12r12
```*


<!--yml

分類:未分類

日期:2024-10-13 06:13:01

-->

# 在 Go (Golang)中用另一個子字串替換一些子字串的例項

> 來源:[`golangbyexample.com/replace-some-instances-substring-go/`](https://golangbyexample.com/replace-some-instances-substring-go/)

目錄

+   概述

+   程式碼:

# **概述**

在 GO 中,字串是 UTF-8 編碼的。GO 的**strings**包提供了一個**Replace**方法,可用於將給定子字串的一些不重疊例項替換為新子字串。它返回字串的副本。

下面是函式的簽名。

```go
func Replace(s, old, new string, n int)
  • 該函式將在字串s中將所有不重疊的old例項替換為new

  • 如果old為空,則在字串s中的每個有效 UTF-8 位元組序列之間插入new

  • 如果n為負,則所有old的例項將被替換為new

讓我們看看工作程式碼。

程式碼:

package main

import (
    "fmt"
    "strings"
)

func main() {
    res := strings.Replace("abcdabxyabr", "ab", "12", 1)
    fmt.Println(res)

    res = strings.Replace("abcdabxyabr", "ab", "12", -1)
    fmt.Println(res)
}

輸出:

12cdabxyabr
12cd12xy12r
```*


<!--yml

類別:未分類

日期:2024-10-13 06:07:33

-->

# 在 Go (Golang) 中表示出生日期

> 來源:[`golangbyexample.com/dob-golang/`](https://golangbyexample.com/dob-golang/)

**time** 包的 **time.Date** 函式可用於建立一個特定日期,以表示出生日期。

請參見以下示例

+   `getDOB` 是一個接受年份、月份和日期並返回日期的函式。

```go
package main

import (
    "fmt"
    "time"
)

const (
    //TimeFormat1 to format date into
    TimeFormat1 = "2006-01-02"
    //TimeFormat2 Other format to format date time
    TimeFormat2 = "January 02, 2006"
)

func main() {
    dob := getDOB(2011, 4, 2)
    fmt.Println(dob.Format(TimeFormat1))
    fmt.Println(dob.Format(TimeFormat2))
}

func getDOB(year, month, day int) time.Time {
    dob := time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.UTC)
    return dob
}

輸出:

2011-04-02
April 02, 2011
  • 日期* 出生日期*

在 Go (Golang) 中返回 200 (狀態正常) 狀態碼的 HTTP 響應 -P

來源:golangbyexample.com/200-http-status-response-golang/

目錄

  • 概述

  • 程式

概述

Golang 的 net/http 包提供了可以用來返回不同狀態碼的狀態碼常量 - golang.org/src/net/http/status.go

同樣可以用來返回 200 (狀態正常) HTTP 狀態碼。 HTTP 200 狀態碼由以下常量定義。

http.StatusOK

在這篇文章中,我們還將看到如何返回 JSON 主體以及 200 (狀態正常) 狀態碼。

程式

以下是相同的程式

package main

import (
	"encoding/json"
	"log"
	"net/http"
)

func main() {
	handler := http.HandlerFunc(handleRequest)
	http.Handle("/example", handler)
	http.ListenAndServe(":8080", nil)
}

func handleRequest(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusOK)
	w.Header().Set("Content-Type", "application/json")
	resp := make(map[string]string)
	resp["message"] = "Status OK"
	jsonResp, err := json.Marshal(resp)
	if err != nil {
		log.Fatalf("Error happened in JSON marshal. Err: %s", err)
	}
	w.Write(jsonResp)
	return
}

在這裡,我們使用 WriteHeader 函式來指定 200 HTTP 狀態碼,並使用 Write 函式返回響應主體。上述程式碼將以下 JSON 請求主體作為響應返回。

{"message":"Status OK"}

執行上述程式。這將在你的本地機器上啟動一個 8080 埠的伺服器。現在對伺服器進行以下 curl 呼叫。

curl -v -X POST http://localhost:8080/example

以下將是輸出。

* Connected to localhost (::1) port 8080 (#0)
> POST /example HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.54.0
> Accept: */*
> 
< HTTP/1.1 200 OK
< Date: Sat, 10 Jul 2021 09:42:59 GMT
< Content-Length: 23
< Content-Type: text/plain; charset=utf-8
< 
* Connection #0 to host localhost left intact
{"message":"Status OK"}

正如你從輸出中看到的,它將正確返回 200 狀態碼以及主體。

你也可以直接將 200 傳遞給 WriteHeader 函式以傳送 200 響應。

w.WriteHeader(200)

這同樣有效。試試看。

同時,請檢視我們的 Golang 高階教程系列 - Golang 高階教程

  • 200* go* golang*

在 Go(Golang)HTTP 響應中返回 201(狀態建立)狀態碼。

來源:golangbyexample.com/201-http-status-response-golang/

目錄

概述

  • 程式

概述

net/http包提供了狀態碼常量,可用於返回不同的狀態碼 - golang.org/src/net/http/status.go

同樣可以用於返回 201(狀態建立)HTTP 狀態碼。HTTP 201 狀態碼由以下常量定義。

http.StatusCreated

在這篇文章中,我們還將看到如何返回 JSON 體以及 201(狀態建立)狀態碼。

程式

以下是相同的程式。

package main

import (
	"encoding/json"
	"log"
	"net/http"
)

func main() {
	handler := http.HandlerFunc(handleRequest)
	http.Handle("/example", handler)
	http.ListenAndServe(":8080", nil)
}

func handleRequest(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusCreated)
	w.Header().Set("Content-Type", "application/json")
	resp := make(map[string]string)
	resp["message"] = "Status Created"
	jsonResp, err := json.Marshal(resp)
	if err != nil {
		log.Fatalf("Error happened in JSON marshal. Err: %s", err)
	}
	w.Write(jsonResp)
	return
}

在這裡,我們使用WriteHeader函式指定 201 HTTP 狀態碼,並使用Write函式返回響應體。上述程式碼返回以下 JSON 請求體作為響應。

{"message":"Status Created"}

執行上述程式,它將在你的本地機器上啟動一個 8080 埠的伺服器。現在進行以下 curl 呼叫到伺服器。

curl -v -X POST http://localhost:8080/example

以下將是輸出。

* Connected to localhost (::1) port 8080 (#0)
> POST /example HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.54.0
> Accept: */*
> 
< HTTP/1.1 201 Created
< Date: Sat, 10 Jul 2021 10:40:33 GMT
< Content-Length: 28
< Content-Type: text/plain; charset=utf-8
< 
* Connection #0 to host localhost left intact
{"message":"Status Created"}

如你所見,輸出將正確返回 201 狀態碼以及主體。

你也可以直接將 201 傳遞給 WriteHeader 函式以傳送 201 響應。

w.WriteHeader(201)

這同樣工作正常。試試看。

此外,檢視我們的 Golang 進階教程系列 - Golang 進階教程

  • 201* go* golang*

在 Go(Golang)中返回 202(StatusAccepted)HTTP 響應

來源:golangbyexample.com/202-status-http-response-go/

目錄

  • 概述

  • 程式

概述

net/http包提供了狀態碼常量,可以用於返回不同的狀態碼 - golang.org/src/net/http/status.go

同樣也可以用於返回 202(StatusAccepted)HTTP 狀態碼。HTTP 202 狀態碼由下面的常量定義。

http.StatusAccepted

在本文中,我們還將看到如何返回帶有 202(StatusAccepted)狀態碼的 JSON 主體

程式

下面是相應的程式

package main

import (
	"encoding/json"
	"log"
	"net/http"
)

func main() {
	handler := http.HandlerFunc(handleRequest)
	http.Handle("/example", handler)
	http.ListenAndServe(":8080", nil)
}

func handleRequest(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusAccepted)
	w.Header().Set("Content-Type", "application/json")
	resp := make(map[string]string)
	resp["message"] = "Status Accepted"
	jsonResp, err := json.Marshal(resp)
	if err != nil {
		log.Fatalf("Error happened in JSON marshal. Err: %s", err)
	}
	w.Write(jsonResp)
	return
}

在這裡我們使用WriteHeader函式來指定 202 HTTP 狀態碼,並使用Write函式返回響應主體。上述程式碼將以下 JSON 請求主體返回作為響應

{"message":"Status Accepted"}

執行上述程式。它將在你的本地機器上啟動一個 8080 埠的伺服器。現在對伺服器進行下面的 curl 呼叫。

curl -v -X POST http://localhost:8080/example

下面將是輸出結果

* Connected to localhost (::1) port 8080 (#0)
> POST /example HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.54.0
> Accept: */*
> 
< HTTP/1.1 202 Accepted
< Date: Sat, 10 Jul 2021 17:42:27 GMT
< Content-Length: 29
< Content-Type: text/plain; charset=utf-8
< 
* Connection #0 to host localhost left intact
{"message":"Status Accepted"}

正如你從輸出中看到的,它將正確返回 202 狀態碼以及主體。

你也可以直接將 202 傳遞給 WriteHeader 函式以傳送 202 響應。

w.WriteHeader(202)

這同樣有效。試試看。

另外,檢視我們的 Golang 高階教程系列 - Golang 高階教程

在 Go(Golang)中返回 400(錯誤請求)狀態碼的 HTTP 響應

來源:golangbyexample.com/400-http-status-response-golang/

目錄

  • 概述

  • 程式

概述

Golang 的net/http包提供了狀態碼常量,可用於返回不同的狀態碼 - golang.org/src/net/http/status.go

同樣也可以用來返回 400(錯誤請求)HTTP 狀態碼。HTTP 400 狀態碼由以下常量定義。

在這篇文章中,我們還將看到如何在返回 400(錯誤請求)狀態碼的同時返回 JSON 主體。

程式

以下是相同的程式

package main

import (
	"net/http"
)

func main() {
	handler := http.HandlerFunc(handleRequest)
	http.Handle("/example", handler)
	http.ListenAndServe(":8080", nil)
}

func handleRequest(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusBadRequest)
	return
}

這裡我們使用WriteHeader函式來指定 HTTP 狀態碼。

執行上述程式。它將在你的本地機器上啟動一個 8080 埠的伺服器。現在向伺服器發出以下 curl 呼叫。

curl -v -X POST http://localhost:8080/example

以下將是輸出

* Connected to localhost (::1) port 8080 (#0)
> POST /example HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.54.0
> Accept: */*
> 
< HTTP/1.1 400 Bad Request
< Date: Sat, 10 Jul 2021 05:50:32 GMT
< Content-Length: 0
< 
* Connection #0 to host localhost left intact

從輸出中可以看到,它將正確返回 400 狀態碼。如果我們還想返回 JSON 錯誤主體,那麼以下是相應的程式碼。

package main

import (
	"encoding/json"
	"log"
	"net/http"
)

func main() {
	handler := http.HandlerFunc(handleRequest)
	http.Handle("/example", handler)
	http.ListenAndServe(":8080", nil)
}

func handleRequest(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusBadRequest)
	w.Header().Set("Content-Type", "application/json")
	resp := make(map[string]string)
	resp["message"] = "Bad Request"
	jsonResp, err := json.Marshal(resp)
	if err != nil {
		log.Fatalf("Error happened in JSON marshal. Err: %s", err)
	}
	w.Write(jsonResp)
	return
}

上述程式碼在響應中返回以下 JSON 請求主體。

{"message":"Bad Request"}

執行上述程式。它將在你的本地機器上啟動一個 8080 埠的伺服器。現在向伺服器發出以下 curl 呼叫。

curl -v -X POST http://localhost:8080/example

以下將是輸出

* Connected to localhost (::1) port 8080 (#0)
> POST /example HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.54.0
> Accept: */*
> 
< HTTP/1.1 400 Bad Request
< Date: Sat, 10 Jul 2021 05:58:42 GMT
< Content-Length: 25
< Content-Type: text/plain; charset=utf-8
< 
* Connection #0 to host localhost left intact
{"message":"Bad Request"}

從輸出中可以看到,它正確返回了 400 狀態碼及其主體。

你也可以直接將 400 傳遞給 WriteHeader 函式以傳送 400 響應。

w.WriteHeader(400)

這也能正常工作。試試看。

另外,檢視我們的 Golang 進階教程系列 - Golang 進階教程

  • 400* go* golang*

相關文章