2024-08-07



package main
 
import (
    "fmt"
    "log"
    "github.com/gocolly/colly"
)
 
func main() {
    // 初始化collector
    c := colly.NewCollector()
 
    // 在onRequestCallback回调中设置请求头
    c.OnRequest(func(r *colly.Request) {
        r.Headers.Set("User-Agent", "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)")
    })
 
    // 定义一个回调函数,处理每个响应
    c.OnResponse(func(r *colly.Response) {
        fmt.Printf("Response received: %s\n", r.Body)
    })
 
    // 设置一个请求URL
    url := "http://example.com"
 
    // 启动collector并发起请求
    c.Visit(url)
}

这段代码使用了colly库来创建一个简单的网络爬虫。首先,我们创建了一个新的Collector实例。然后,我们设置了一个请求头的回调函数,以此来定义爬虫的用户代理。接着,我们定义了一个响应处理的回调函数,这样我们就可以在收到响应时打印出响应的内容。最后,我们指定了想要爬取的URL并开始了爬取过程。这个例子展示了如何使用colly库的基本功能来创建一个简单的网络爬虫。

2024-08-07



package main
 
import (
    "fmt"
)
 
// 定义一个函数,使用defer关键字来延迟执行关闭文件的操作
func readFile(path string) {
    file, err := os.Open(path)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    // 使用defer关键字来确保文件在函数结束时关闭
    defer file.Close()
 
    // 这里可以执行文件读取的操作
    content, err := ioutil.ReadAll(file)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    fmt.Println("File content:", string(content))
}
 
func main() {
    readFile("example.txt")
}

这段代码演示了如何在Go语言中使用defer关键字来确保文件在读取操作后能够被正确关闭。这是一个非常重要的实践,因为它能够避免文件资源泄露的问题。

2024-08-07

为了配置Go中国镜像代理服务,你需要设置环境变量GOPROXY。以下是如何设置的示例代码:




# 设置GOPROXY环境变量
export GOPROXY=https://goproxy.cn,direct
 
# 验证设置是否成功
go env GOPROXY

在你的操作系统中打开终端或命令行界面,并输入上述命令。这会将Go模块代理设置为goproxy.cn,并且如果该代理无法使用,则会直接访问模块内容。

如果你使用的是Windows系统,可以使用以下命令来设置环境变量:




:: 设置GOPROXY环境变量
setx GOPROXY https://goproxy.cn,direct
 
:: 验证设置是否成功
go env GOPROXY

请注意,这些命令只在当前终端会话中设置环境变量。要永久设置环境变量,你需要在系统的环境变量设置中进行配置。

2024-08-07

TRPC是一个基于Go的高性能RPC框架,它提供了代码生成、路由、中间件等功能。以下是一个简单的TRPC示例,展示了如何定义服务、创建服务器以及调用服务。

首先,你需要安装TRPC:




go get github.com/cs3238-2021/go-trpc

定义服务:




// hello.proto
syntax = "proto3";
 
package pb;
 
service Hello {
  rpc Hello(HelloRequest) returns (HelloResponse);
}
 
message HelloRequest {
  string name = 1;
}
 
message HelloResponse {
  string message = 1;
}

生成Go代码:




trpc-go-gen -in hello.proto -out .

实现服务:




package main
 
import (
    "context"
    "fmt"
    "github.com/cs3238-2021/go-trpc/examples/helloworld/pb"
)
 
type helloService struct{}
 
func (h *helloService) Hello(ctx context.Context, req *pb.HelloRequest) (*pb.HelloResponse, error) {
    return &pb.HelloResponse{Message: "Hello, " + req.Name + "!"}, nil
}
 
func main() {
    server := trpc.NewServer()
    server.Register(new(helloService))
    // ... start the server
}

启动服务并调用服务:




package main
 
import (
    "context"
    "fmt"
    "log"
    "net"
 
    "github.com/cs3238-2021/go-trpc/examples/helloworld/pb"
)
 
func main() {
    listener, err := net.Listen("tcp", ":8080")
    if err != nil {
        log.Fatal(err)
    }
    defer listener.Close()
 
    server := trpc.NewServer()
    server.Register(new(helloService))
 
    go func() {
        if err := server.Serve(listener); err != nil {
            log.Fatal(err)
        }
    }()
 
    client := trpc.NewClient(listener.Addr().String())
    resp, err := client.Call(context.Background(), &pb.HelloRequest{Name: "World"})
    if err != nil {
        log.Fatal(err)
    }
 
    fmt.Println(resp.(*pb.HelloResponse).Message)
}

以上代码展示了如何定义一个RPC服务,如何实现它,以及如何启动服务器并从客户端调用该服务。这个例子是基于一个简单的“Hello World”服务,但TRPC可以用于更复杂的应用程序。

2024-08-07

context包提供了管理并发操作中的取消信号、超时值、键值对等上下文数据的机制。

概述

context包中的Context接口提供了以下方法:

  • Deadline() (deadline time.Time, ok bool): 返回上下文被取消的截止日期。
  • Done() <-chan struct{}: 返回一个channel,当上下文被取消时,该channel会关闭。
  • Err() error: 返回导致上下文被取消的原因。
  • Value(key interface{}) interface{}: 返回与上下文关联的键值对。

使用示例

创建带有超时的上下文:




ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
 
// 使用ctx进行操作...

在goroutine中处理超时:




ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
 
go func() {
    select {
    case <-ctx.Done():
        fmt.Println("超时或上下文被取消,退出goroutine。")
        return
    case <-time.After(20 * time.Second):
        fmt.Println("goroutine运行时间超过预定上下文时间。")
    }
}()
 
// 执行其他任务...

在HTTP服务中使用上下文传递请求范围的值:




func MyHandler(w http.ResponseWriter, r *http.Request) {
    ctx := context.WithValue(r.Context(), "key", "value")
    go HandleRequest(ctx)
}
 
func HandleRequest(ctx context.Context) {
    value := ctx.Value("key")
    // 处理value...
}

以上代码展示了如何在Go语言中使用context包来管理并发操作的上下文,包括创建带有超时和取消功能的上下文、在goroutine中响应上下文的取消信号、在HTTP服务中传递带有键值对的上下文数据。

2024-08-07

Go语言是一门现代的、静态类型的编译型语言,它的设计目标是简洁、快速编译、并行处理、内存安全、高效并发执行。以下是Go语言的一些核心知识点:

  1. 简洁的语法:Go语言的语法非常简洁,学习起来相对容易。
  2. 静态类型检查:Go语言是静态类型的语言,意味着所有变量在编译时就必须确定其类型。
  3. 并发编程:Go语言内置了goroutine的概念,可以非常简单的编写并发程序。
  4. 内存管理:Go语言自动进行内存管理,你不需要手动删除不再使用的内存。
  5. 编译速度快:Go语言编译速度非常快,可以快速的进行开发和测试。
  6. 标准库丰富:Go语言有一个非常丰富的标准库,提供了很多现成的工具可以使用。
  7. 性能优秀:Go语言的性能也很优秀,尤其是在网络编程和多核并行处理上。
  8. 编译成机器码:Go语言编译后的程序是机器码,所以它可以跳过解释器层,直接执行。
  9. 语言设计的理念:简洁、明确、安全、并发。

Go语言的核心知识点还有很多,例如指针、结构体、接口、错误处理、切片(slices)和映射(maps)等。

以下是一个简单的Go程序示例,它定义了一个函数,该函数计算并返回两个整数的和:




package main
 
import "fmt"
 
func add(a int, b int) int {
    return a + b
}
 
func main() {
    fmt.Println(add(1, 2))
}

这个程序首先导入了fmt包,用于格式化输入/输出。然后定义了一个名为add的函数,该函数接受两个整数作为参数并返回它们的和。最后在main函数中调用add函数,并打印结果。

2024-08-07

在使用VSCode编写Go语言时,可能会遇到以下几个大坑:

  1. 单元测试:Go语言的单元测试文件通常以 _test.go 结尾,在VSCode中,默认情况下,测试文件不会被识别和编译。解决方法是在 go.mod 文件所在目录打开VSCode,或者在VSCode设置中启用 "go.inferGopath": true
  2. goimportsgoimports 是Go语言的一个工具,用于格式化导入的包,并添加任何缺失的包。在VSCode中,可以通过安装Go插件并启用 go.useCodeSnippetsOnFunctionSuggest 选项来使用 goimports
  3. 研发4面真题解析:在VSCode中,可以通过安装Linux内核开发插件,并在 settings.json 中配置 "files.associations": {"*.ko": "linux-kernel-assembly"} 来提供Linux内核模块的语法高亮和缩进。

以下是解决这些问题的示例配置:




{
    "go.inferGopath": true,
    "go.useCodeSnippetsOnFunctionSuggest": true,
    "[linux-kernel-assembly]": {
        "editor.tabSize": 8
    },
    "files.associations": {
        "*.ko": "linux-kernel-assembly"
    }
}

请注意,具体配置可能会随着VSCode和Go插件的更新而变化,请根据实际情况调整配置。

2024-08-07



package main
 
import (
    "fmt"
    "sync"
    "time"
)
 
func worker(id int, wg *sync.WaitGroup, jobs <-chan int, results chan<- int) {
    defer wg.Done() // 确保该协程结束时通知主协程
    for job := range jobs {
        // 模拟耗时工作
        fmt.Println("Worker", id, "started job", job)
        time.Sleep(time.Second)
        fmt.Println("Worker", id, "finished job", job)
 
        results <- job * 2 // 发送结果到results通道
    }
}
 
func main() {
    var wg sync.WaitGroup
    jobs := make(chan int, 100) // 创建一个缓冲为100的通道
    results := make(chan int, 100) // 创建一个缓冲为100的通道
 
    // 这里启动了4个工作协程
    for i := 1; i <= 4; i++ {
        wg.Add(1)
        go worker(i, &wg, jobs, results)
    }
 
    // 发送10个作业
    for j := 1; j <= 10; j++ {
        jobs <- j
    }
    close(jobs) // 关闭jobs通道,表示不会再有新的作业
 
    // 等待所有作业完成
    wg.Wait()
    close(results) // 所有作业完成后,关闭results通道
 
    // 打印结果
    for result := range results {
        fmt.Println(result)
    }
}

这段代码创建了一个工作池,其中有4个工作协程处理作业。主协程发送10个作业并关闭作业通道,工作协程处理完作业后,将结果发送到结果通道,并在所有作业处理完成后关闭结果通道。最后,主协程打印所有结果。这个例子展示了Go语言中协程和通道的基本使用方法,以及如何有效地进行并发任务处理。

2024-08-07

在 Go 语言中,map 是一种内置的数据类型,它可以存储任意类型的无序的键值对。

以下是 Go 语言中 Map 的一些常见操作:

  1. 声明 Map

声明一个 map 需要指定键和值的类型。这里,我们使用字符串作为键,整数作为值。




var map1 map[string]int
map1 = make(map[string]int)
  1. 向 Map 添加元素



map1["one"] = 1
map1["two"] = 2
map1["three"] = 3
  1. 从 Map 中删除元素



delete(map1, "one") // 删除键为 "one" 的元素
  1. 遍历 Map

Go 语言中遍历 map 的标准方法是使用 for-range 循环。




for key, value := range map1 {
    fmt.Printf("Key: %s, Value: %d\n", key, value)
}
  1. 检查 Map 中是否存在某个键

Go 语言中,我们可以通过判断该键是否存在来判断该键值对是否在 Map 中。




value, ok := map1["two"]
if ok {
    fmt.Printf("Key 'two' exists with value %d\n", value)
} else {
    fmt.Println("Key 'two' does not exist")
}
  1. 使用值类型为指针的 Map



var map2 map[string]*int
map2 = make(map[string]*int)
 
a := 1
map2["one"] = &a

以上就是 Go 语言中 Map 的一些基本操作。

2024-08-07

在macOS本地环境配置MySQL、MongoDB和Redis的步骤如下:

  1. MySQL安装和配置:

    • 使用Homebrew安装MySQL:

      
      
      
      /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
      brew update
      brew install mysql
    • 启动MySQL服务:

      
      
      
      brew services start mysql
    • 设置初始密码:

      
      
      
      mysql_secure_installation
  2. MongoDB安装和配置:

    • 使用Homebrew安装MongoDB:

      
      
      
      brew update
      brew install mongodb-community
    • 创建数据目录:

      
      
      
      mkdir -p /usr/local/var/mongodb
    • 启动MongoDB服务:

      
      
      
      mongod --config /usr/local/etc/mongod.conf
  3. Redis安装和配置:

    • 使用Homebrew安装Redis:

      
      
      
      brew update
      brew install redis
    • 启动Redis服务:

      
      
      
      brew services start redis

以上步骤安装和启动了MySQL、MongoDB和Redis,并将它们作为服务运行。你可以使用相应的客户端工具(如MySQL Workbench, MongoDB Compass, 或redis-cli)来管理数据库。

注意:确保在安装和配置过程中遵循各自的最佳实践和安全指导。例如,对于MySQL和MongoDB,应设置复杂密码,并且在生产环境中应该采取额外的安全措施。对于Redis,应设置合适的访问控制,并仅在必要时监听外部接口。