2024-08-27

Golang 提供了一些内建函数,这些函数可以直接使用,无需额外的包导入。以下是一些常见的 Golang 内建函数:

  1. len:用于获取数组、切片、字符串、Map 的长度。



str := "Hello, World!"
length := len(str)
fmt.Println(length) // 输出:13
  1. cap:用于获取数组、切片、Map、channel 的容量。



slice := make([]int, 10)
capacity := cap(slice)
fmt.Println(capacity) // 输出:10
  1. newmakenew 用于分配内存,返回类型的指针;make 用于内存分配并初始化,返回初始化后的(引用)类型值。



// new
p := new(int)  
fmt.Println(*p) // 输出:0
 
// make
s := make([]int, 10)
fmt.Println(s) // 输出:[0 0 0 0 0 0 0 0 0 0]
  1. append:用于添加元素到数组、切片中。



slice := []string{"Hello", "World"}
slice = append(slice, "!" )
fmt.Println(slice) // 输出:[Hello World !]
  1. copy:用于复制数组、切片中的元素。



src := []int{1, 2, 3, 4, 5}
dst := []int{10, 20, 30, 40, 50}
n := copy(dst, src)
fmt.Println(n) // 输出:5
fmt.Println(dst) // 输出:[1 2 3 4 5]
  1. delete:用于从 Map 中删除键值对。



m := map[string]int{"one": 1, "two": 2}
delete(m, "one")
fmt.Println(m) // 输出:map[two:2]
  1. panicrecoverpanic 用于引发一个异常,recover 用于恢复程序的正常运行。



func main() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Print("Recovered in main", r)
        }
    }()
    panic("crash")
}
  1. printprintln:用于打印输出。



print("Hello, ")
println("World!") // 输出:Hello, World!
  1. realimag:用于获取复数的实部和虚部。



c := 3.14 + 1.23i
realPart := real(c)
imagPart := imag(c)
fmt.Println(realPart) // 输出:3.14
fmt.Println(imagPart) // 输出:1.23
  1. close:用于关闭 channel。



c := make(chan int)
go func() {
    c <- 1
}()
close(c)

这些内建函数提供了 Golang 编程的基本功能,可以根据需要选择使用。

2024-08-27



package main
 
import (
    "os"
    "text/template"
)
 
// 定义一个结构体,用于传递给模板
type Person struct {
    Name string
    Age  int
}
 
// 定义模板文本
const tmpl = `Hello, {{.Name}}
You are {{.Age}} years old.
`
 
func main() {
    // 创建一个新的模板并解析模板文本
    t := template.Must(template.New("hello").Parse(tmpl))
 
    // 创建一个Person实例并初始化
    p := Person{Name: "Alice", Age: 30}
 
    // 执行模板并将结果写入os.Stdout
    err := t.Execute(os.Stdout, p)
    if err != nil {
        panic(err)
    }
}

这段代码定义了一个Person结构体和一个模板文本tmpl。然后创建了一个新的模板,解析了模板文本,并创建了一个Person实例。最后,通过调用Execute方法将模板和实例数据结合并输出到控制台。如果在执行过程中发生错误,代码将使用panic函数打印错误信息。这是一个简单的模板使用示例,展示了Go语言中text/template包的基本用法。

2024-08-27

net/http/cookiejar 包提供了一个实现了http.CookieJar接口的结构体Jar,它可以自动在客户端请求中存储和发送 cookies,并从服务器响应中接收 cookies。

以下是使用cookiejar包的一个简单示例:




package main
 
import (
    "fmt"
    "net/http"
    "net/http/cookiejar"
    "io/ioutil"
)
 
func main() {
    // 创建一个cookiejar
    jar, err := cookiejar.New(nil)
    if err != nil {
        panic(err)
    }
 
    client := &http.Client{
        Jar: jar,
    }
 
    // 发送一个HTTP GET请求
    resp, err := client.Get("http://example.com")
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()
 
    // 读取响应体
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        panic(err)
    }
 
    fmt.Println(string(body))
 
    // 打印存储的cookies
    for _, cookie := range jar.Cookies(nil) {
        fmt.Printf("Cookie: %s=%s\n", cookie.Name, cookie.Value)
    }
}

在这个例子中,我们首先创建了一个Jar实例,然后用它来初始化一个http.ClientJar字段。这样,当我们使用这个客户端发送请求时,它会自动处理接收到的cookies,并在将来的请求中发送它们。我们通过client.Get发送一个HTTP GET请求,然后打印出响应体和存储的cookies。

2024-08-27

在Golang中,你可以使用sync.WaitGroupchan(通道)来限制并发数。以下是一个示例代码,它使用一个有界的通道来控制并发数:




package main
 
import (
    "fmt"
    "sync"
    "time"
)
 
func main() {
    concurrency := 3 // 你想要限制的并发数
    var wg sync.WaitGroup
    queue := make(chan struct{}, concurrency) // 创建一个有界通道
 
    for i := 0; i < 10; i++ { // 模拟10个任务
        wg.Add(1)
        queue <- struct{}{} // 放入一个元素到通道,限制并发数
        go func(id int) {
            defer wg.Done()
            defer func() { <-queue }() // 任务完成后从通道移除一个元素
            // 模拟耗时操作
            time.Sleep(time.Second)
            fmt.Println("Task", id, "is running")
        }(i)
    }
 
    wg.Wait() // 等待所有任务完成
}

在这个例子中,我们使用了一个sync.WaitGroup来等待所有并发的goroutines完成,同时使用了一个chan struct{}(无缓冲的通道)或者有缓冲的通道(如上例的queue)来限制并发的数量。每个goroutine在启动前向通道中放入一个元素,执行完任务后再从通道中移除元素。这样可以确保同时运行的goroutines数量不会超过我们设定的限制。

2024-08-27

在 Golang 中,文件的读写主要是通过 osio 包来实现的。以下是一些基本的文件读写操作:

  1. 使用 os.Open 打开文件进行读操作:



package main
 
import (
    "fmt"
    "io/ioutil"
    "os"
)
 
func main() {
    file, err := os.Open("test.txt")
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    defer file.Close()
 
    data, err := ioutil.ReadAll(file)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
 
    fmt.Println("Contents of file:", string(data))
}
  1. 使用 os.Create 创建文件进行写操作:



package main
 
import (
    "fmt"
    "os"
)
 
func main() {
    file, err := os.Create("test.txt")
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    defer file.Close()
 
    _, err = file.Write([]byte("Hello, World!"))
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
 
    fmt.Println("Content written to file")
}
  1. 使用 bufio 包进行文件的高效读写操作:



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



package main
 
import (
    "bufio"
    "fmt"
    "os"
)
 
func main() {
    file, err := os.Create("test.txt")
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    defer file.Close()
 
    writer := bufio.NewWriter(file)
    _, err = writer.WriteString("Hello, World!")
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
 
    err = writer.Flush()
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
 
    fmt.Println("Content written to file")
}
  1. 使用 ioutil.ReadFileioutil.WriteFile 进行一次性读写操作:



package main
 
import (
    "fmt"
    "io/ioutil"
)
 
func main() {
    data, err := ioutil.ReadFile("test.txt")
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
 
    fmt.Println("Contents of file:", string(data))
 
    err = ioutil.WriteFile("test.txt", []byte("Hello, World!"), 0644)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
 
    fmt.Println("Content written to file")
}

以上是一些基本的文件读写操作,在实际应用中可以根据需要选择合适的方法。

2024-08-27



package main
 
import (
    "errors"
    "fmt"
)
 
// 定义一个自定义错误
var ErrInvalidInput = errors.New("invalid input")
 
// 一个可能会返回错误的函数
func mightFail() error {
    // 假设这里有一些逻辑导致了失败
    return ErrInvalidInput
}
 
// 一个调用可能会失败的函数的函数,并处理错误
func handleErrors() {
    if err := mightFail(); err != nil {
        // 如果发生错误,打印错误并退出
        fmt.Println("An error occurred:", err)
        // 如果需要,可以选择使用 panic 在错误严重到需要中止程序时
        panic(err)
    }
}
 
func main() {
    handleErrors()
}

这段代码定义了一个自定义错误ErrInvalidInput,并在函数mightFail中返回这个错误。函数handleErrors调用了mightFail,并通过检查返回的错误来处理可能发生的失败。如果发生错误,它会打印错误消息并退出程序。如果错误严重到需要程序立即终止,可以选择使用panic。这是一个简单的错误处理和异常管理的例子。

2024-08-27

在Go语言中,闭包可以用来处理错误,特别是在异步或者多个goroutine中。以下是一个简单的例子,展示了如何使用匿名函数(闭包)来处理错误:




package main
 
import (
    "fmt"
    "time"
)
 
func main() {
    // 定义一个处理错误的匿名函数
    handleError := func(err error) {
        if err != nil {
            fmt.Println("发生错误:", err)
        }
    }
 
    // 在一个goroutine中模拟发生错误
    go func() {
        err := doSomething()
        handleError(err) // 使用闭包处理错误
    }()
 
    // 阻塞主goroutine,确保程序不会提前退出
    time.Sleep(1 * time.Second)
}
 
// 一个可能会失败的函数
func doSomething() error {
    // 这里模拟一个错误
    return fmt.Errorf("模拟的错误")
}

在这个例子中,我们定义了一个匿名函数handleError,它接受一个error类型的参数。如果参数不为nil,则打印错误信息。然后在一个新的goroutine中,我们调用了doSomething函数,并将返回的错误传递给handleError函数进行处理。这展示了如何在Go语言中使用闭包来处理异步错误。

2024-08-27

在Golang中,for 结构主要用于循环。Golang 提供了 for、range 和 select 三种类型的循环。

  1. 基本的 for 循环



for i := 0; i < 10; i++ {
    fmt.Println(i)
}
  1. For-Each 循环,使用 range



numbers := [6]int{0, 1, 2, 3, 4, 5}
for i, x := range numbers {
    fmt.Printf("Index: %d, Number: %d\n", i, x)
}
  1. Select 语句,类似于其他语言的 switch 语句,但是只能用于选择协程。



channels := []chan int{make(chan int), make(chan int)}
 
for i := 0; i < 2; i++ {
    go func(idx int) {
        channels[idx] <- idx * 2
    }(i)
}
 
for i := 0; i < 2; i++ {
    select {
    case v := <-channels[0]:
        fmt.Println("channel 0 returned", v)
    case v := <-channels[1]:
        fmt.Println("channel 1 returned", v)
    }
}

以上就是 Golang 中 for 结构的基本使用。

2024-08-27

golang.org/x/text/unicode/bidi 包提供了对 Unicode 双向文本布局算法的实现。双向文本指的是同时包含从左到右和从右到左文本的文本,这通常在处理特定语言如阿拉伯语和希伯来语时遇到。

以下是使用 bidi 包中的一些主要函数的示例代码:




package main
 
import (
    "fmt"
    "golang.org/x/text/unicode/bidi"
)
 
func main() {
    // 示例文本,包含从左到右的英文和从右到左的阿拉伯文
    text := "Hello مرحبا"
 
    // 计算文本的Bidi类型
    types := bidi.Classify(text)
 
    // 根据Bidi类型对文本进行处理
    runes := []rune(text)
    result := bidi.Reorder(runes, types)
 
    // 打印结果
    fmt.Println(string(result))
}

在这个例子中,Classify 函数会分析文本并确定每个字符的Bidi类型,然后 Reorder 函数会根据这些类型重新排列文本,以确保正确的视觉显示顺序。

注意:在实际使用中,你可能需要先通过 go get 命令获取 golang.org/x/text 包及其依赖。




go get -u golang.org/x/text

然后,你可以像上面示例中那样导入并使用 bidi 包。

2024-08-27

在Go语言中,你可以使用cryptocrypto/rand标准库来进行密码学操作。以下是一些基本的密码学操作的示例代码:

  1. 生成随机数:



package main
 
import (
    "crypto/rand"
    "fmt"
    "io"
)
 
func main() {
    randomNumber := make([]byte, 8) // 创建一个8字节的切片来存储随机数
    _, err := io.ReadFull(rand.Reader, randomNumber) // 从加密的随机数生成器读取足够的随机数
    if err != nil {
        fmt.Println("Error generating random number:", err)
        return
    }
    fmt.Printf("Random number: %x\n", randomNumber)
}
  1. 使用SHA256进行哈希:



package main
 
import (
    "crypto/sha256"
    "fmt"
)
 
func main() {
    data := []byte("hello world")
    hash := sha256.Sum256(data)
    fmt.Printf("SHA256 hash: %x\n", hash)
}
  1. 使用AES-256-GCM进行加密和认证:



package main
 
import (
    "crypto/aes"
    "crypto/cipher"
    "crypto/rand"
    "encoding/base64"
    "io"
    "log"
)
 
func encrypt(plaintext string) (string, error) {
    key := make([]byte, 32) // AES-256的密钥长度
    if _, err := io.ReadFull(rand.Reader, key); err != nil {
        return "", err
    }
 
    plaintextBytes := []byte(plaintext)
    block, err := aes.NewCipher(key)
    if err != nil {
        return "", err
    }
 
    aesgcm, err := cipher.NewGCM(block)
    if err != nil {
        return "", err
    }
 
    nonce := make([]byte, 12) // GCM非常安全,所以使用足够长的nonce
    if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
        return "", err
    }
 
    ciphertext := aesgcm.Seal(nil, nonce, plaintextBytes, nil)
    return base64.StdEncoding.EncodeToString(append(nonce, ciphertext...)), nil
}
 
func decrypt(ciphertext string) (string, error) {
    ciphertextBytes, err := base64.StdEncoding.DecodeString(ciphertext)
    if err != nil {
        return "", err
    }
 
    key := ciphertextBytes[:len(ciphertextBytes)-12]
    block, err := aes.NewCipher(key)
    if err != nil {
        return "", err
    }
 
    aesgcm, err := cipher.NewGCM(block)
    if err != nil {
        return "", err
    }
 
    nonce := ciphertextBytes[len(ciphertextBytes)-12:]
    plaintext, err := aesgcm.Open(nil, nonce, ciphertextBytes[len(nonce):], nil)
    if err != nil {
        return "", err
    }
 
    return string(plaintext), nil
}
 
func main() {
    encrypted, err := encrypt("hello world")
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("Encrypted:", encrypted)
 
    decrypted, err := decrypt(encrypted)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("Decrypted:", decrypted)
}

这些例子展示了如何在Go中生成随机数、进行哈希、创建