2024-08-23

在Go语言中,你可以使用crypto/rsa包来进行RSA加密和解密。以下是一个简单的例子,展示了如何使用公钥进行签名(加密)和如何使用私钥进行验签(解密)。




package main
 
import (
    "crypto/rand"
    "crypto/rsa"
    "crypto/x509"
    "encoding/pem"
    "fmt"
)
 
func main() {
    // 生成RSA密钥对
    privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
    if err != nil {
        panic(err)
    }
    publicKey := &privateKey.PublicKey
 
    // 签名
    message := []byte("Hello, third-party API!")
    signature, err := rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, message)
    if err != nil {
        panic(err)
    }
    fmt.Printf("Signature: %x\n", signature)
 
    // 验签
    err = rsa.VerifyPKCS1v15(publicKey, crypto.SHA256, message, signature)
    if err != nil {
        panic(err)
    }
    fmt.Println("Verification succeeded!")
}

在这个例子中,我们首先生成了一个RSA密钥对。然后,我们使用私钥对一个消息进行了签名,生成了加密的签名。最后,我们使用公钥验证了这个签名,确保消息的完整性。

请注意,这个例子是为了演示目的而简化的。在实际应用中,密钥的生成和管理应该更加安全,密钥可能会从外部源(例如密钥管理服务)加载,签名和验签的过程可能会更加复杂,涉及到与第三方接口的协议约定。

2024-08-23

以下是一个简化的代码实例,展示了如何在Go中使用Gin框架和Vue 3创建一个简单的博客系统。

Go (Gin + GORM):




package main
 
import (
    "github.com/gin-gonic/gin"
    "github.com/gin-gonic/gin/binding"
    "gorm.io/driver/sqlite"
    "gorm.io/gorm"
)
 
type Post struct {
    gorm.Model
    Title   string
    Content string
}
 
func main() {
    r := gin.Default()
    db, err := gorm.Open(sqlite.Open("blog.db"), &gorm.Config{})
    if err != nil {
        panic("failed to connect database")
    }
    db.AutoMigrate(&Post{})
 
    // 创建博客
    r.POST("/posts", func(c *gin.Context) {
        var post Post
        if err := c.ShouldBindBodyWith(&post, binding.JSON); err != nil {
            c.JSON(400, gin.H{"error": err.Error()})
            return
        }
        db.Create(&post)
        c.JSON(200, post)
    })
 
    // 获取博客列表
    r.GET("/posts", func(c *gin.Context) {
        var posts []Post
        db.Find(&posts)
        c.JSON(200, posts)
    })
 
    r.Run()
}

Vue 3 (Vue CLI + Axios):




<template>
  <div>
    <input v-model="post.title" placeholder="Title" />
    <textarea v-model="post.content" placeholder="Content"></textarea>
    <button @click="createPost">Create Post</button>
  </div>
</template>
 
<script>
import axios from 'axios';
 
export default {
  data() {
    return {
      post: {
        title: '',
        content: ''
      }
    };
  },
  methods: {
    async createPost() {
      try {
        const response = await axios.post('http://localhost:8080/posts', this.post);
        console.log(response.data);
      } catch (error) {
        console.error(error);
      }
    }
  }
};
</script>

这个简单的例子展示了如何使用Gin和GORM在Go端创建RESTful API,以及如何在Vue 3中使用Axios与该API进行交互。这个系统可以扩展,添加更多的功能,比如用户认证、分页、搜索等。

2024-08-23



package main
 
import (
    "context"
    "fmt"
    "os"
    "os/signal"
    "syscall"
    "time"
)
 
// 优雅地重启服务的示例函数
func gracefulRestart(ctx context.Context) error {
    // 创建系统信号监听器,监听中断(interrupt)信号
    stop := make(chan os.Signal, 1)
    signal.Notify(stop, syscall.SIGINT) // 当按下Ctrl+C时,会发送SIGINT信号
 
    // 创建一个超时上下文,当服务在2s内没有正常关闭时会强制退出
    var cancel context.CancelFunc
    ctx, cancel = context.WithTimeout(ctx, 2*time.Second)
    defer cancel()
 
    // 阻塞等待接收信号
    <-stop
 
    // 在这里可以添加代码来关闭外部资源(如数据库连接、清理文件等)
    // 这里只是简单打印信息
    fmt.Println("服务正在优雅地关闭...")
 
    // 返回nil表示不需要进行错误处理,因为优雅关闭不应该有错误返回
    return nil
}
 
func main() {
    // 创建一个空的上下文
    ctx := context.Background()
 
    // 调用优雅重启函数
    if err := gracefulRestart(ctx); err != nil {
        fmt.Println("优雅关闭失败:", err)
        os.Exit(1)
    }
 
    fmt.Println("优雅关闭成功")
    os.Exit(0)
}

这段代码演示了如何在Go语言中实现一个简单的优雅重启逻辑。它创建了一个监听系统中断信号(如Ctrl+C)的goroutine,并设置了一个超时上下文,以确定优雅关闭的最后期限。在实际应用中,你可以在gracefulRestart函数中添加关闭数据库连接、清理资源等逻辑。

2024-08-23



package main
 
import (
    "bytes"
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
)
 
// 假设我们有一个API的请求结构体
type ApiRequest struct {
    Field1 string `json:"field1"`
    Field2 int    `json:"field2"`
}
 
// 假设我们有一个API的响应结构体
type ApiResponse struct {
    Code    int    `json:"code"`
    Message string `json:"message"`
}
 
func main() {
    // 创建API请求对象
    request := ApiRequest{
        Field1: "value1",
        Field2: 123,
    }
 
    // 序列化请求对象为JSON格式
    requestBody, err := json.Marshal(request)
    if err != nil {
        panic(err)
    }
 
    // 发起POST请求到第三方API
    resp, err := http.Post("https://api.example.com/endpoint", "application/json", bytes.NewBuffer(requestBody))
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()
 
    // 读取响应体
    responseBody, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        panic(err)
    }
 
    // 反序列化响应体到响应对象
    var response ApiResponse
    err = json.Unmarshal(responseBody, &response)
    if err != nil {
        panic(err)
    }
 
    // 输出API响应结果
    fmt.Printf("API Response: %+v\n", response)
}

这段代码展示了如何在Go中创建一个HTTP POST请求,发送JSON格式的数据到第三方API,并处理返回的JSON响应。代码中包含了错误处理,确保在发生任何错误时程序不会崩溃。

2024-08-23



package main
 
import (
    "fmt"
    "time"
)
 
func worker(id int, c chan int) {
    for n := range c {
        fmt.Printf("Worker %d received %d\n", id, n)
        time.Sleep(time.Second)
    }
}
 
func main() {
    const numWorkers = 3
    const numMessages = 5
 
    workers := make([]chan int, numWorkers)
 
    for i := range workers {
        workers[i] = make(chan int)
        go worker(i, workers[i])
    }
 
    for i := 0; i < numMessages; i++ {
        time.Sleep(time.Second)
        fmt.Printf("Master sending %d\n", i)
        for _, worker := range workers {
            worker <- i
        }
    }
 
    for _, worker := range workers {
        close(worker)
    }
 
    fmt.Scanln() // 阻塞主goroutine,防止程序立即退出
}

这段代码修复了原始代码中的问题,并提供了一个简单的Go程序示例,它创建了一个工作池,并向每个工作程序平均分配了任务。每个工作程序在自己的goroutine中运行,并且主goroutine会等待用户输入来防止程序立即退出。这个例子展示了Go语言中协程、通道和工作池模式的基本使用方法。

2024-08-23



# 安装并配置内网穿透工具 - 以 `frp` 为例
# 下载 frp 到你的 Windows 系统
frp_windows_amd64.zip (https://github.com/fatedier/frp/releases)
# 解压缩
 
# 配置 frps.ini
[common]
bind_port = 7000
 
# 启动 frps
./frps -c frps.ini
 
# 在你的 Linux 服务器上安装 frpc
# 下载 frp 到你的 Linux 服务器
frp_linux_amd64.zip (https://github.com/fatedier/frp/releases)
# 解压缩
 
# 配置 frpc.ini
[common]
server_addr = <你的 Windows IP>
server_port = 7000
 
[ssh]
type = tcp
local_ip = 127.0.0.1
local_port = 22
remote_port = 6000
 
[tunnel]
type = tcp
remote_port = 7001
local_ip = 127.0.0.1
local_port = 6333
 
# 启动 frpc
./frpc -c frpc.ini
 
# 在 GoLand 中配置 SSH 远程开发环境
# 打开 GoLand,选择 `File` > `Settings` > `Build, Execution, Deployment` > `Deployment`
# 点击 `+` 添加一个新的部署配置,选择 `SFTP`
# 填写你的服务器信息,用户名、主机、私钥等
# 在 `Mappings` 中配置本地目录与远程服务器目录的映射
# 保存配置并测试连接
 
# 配置端口转发,以便于 GoLand 可以通过内网穿透连接到你的开发环境
# 在 frpc.ini 中添加如下配置
[goland_debug_server]
type = tcp
local_ip = 127.0.0.1
local_port = 6333
remote_port = 6333
 
# 重启 frpc 使配置生效
 
# 在 GoLand 中配置远程解释器
# 选择 `File` > `Settings` > `Languages & Frameworks` > `Go` > `Go Modules (vgo)` 或 `Go SDK`
# 在 `SSH Interpreter` 中配置你的 SSH 连接信息,选择你刚才创建的部署配置
# 保存设置并重新启动 GoLand
 
# 现在你可以在 GoLand 中远程编辑、编译和调试 Linux 服务器上的 Go 代码了

这个例子展示了如何使用内网穿透工具 frp 将你的本地开发环境与远程的 Linux 服务器连接起来,并在 GoLand 中配置相关设置以实现远程开发和调试。这样可以在没有公网 IP 的情况下进行开发工作,特别适合家庭、办公室网络环境或在教育、个人项目中使用。

2024-08-23

go-callvis是一个用来可视化Go语言程序中函数调用关系的工具。以下是如何使用go-callvis的简单示例:

首先,你需要安装go-callvis:




go get -u github.com/ofabry/go-callvis

然后,你可以使用以下命令来生成一个HTML文件,其中包含了你的Go程序的函数调用关系图:




go-callvis -group pkg -min 1 your/package | fgrep -v "github.com/ofabry/go-callvis" > /tmp/callvis.html

这里的-group pkg选项表示按照包来分组显示调用关系,-min 1表示只显示最小深度为1的节点,your/package是你想要分析的Go语言包的路径。

最后,你可以在浏览器中打开生成的HTML文件来查看调用关系图:




open /tmp/callvis.html

这个命令会在你的默认浏览器中打开HTML文件,显示函数调用关系的可视化图。你可以通过拖动和缩放来浏览图表,也可以使用顶部的选择框来过滤特定的包或函数。

2024-08-23



package main
 
import (
    "fmt"
    "github.com/google/uuid"
)
 
func main() {
    // 使用Go标准库生成UUID
    u1 := uuid.New()
    fmt.Println("UUID Version 4:", u1)
 
    // 生成UUID并转化为字符串形式
    u2 := uuid.NewString()
    fmt.Println("UUID Version 4 (String):", u2)
}

这段代码演示了如何在Go语言中使用github.com/google/uuid库生成UUID。uuid.New()函数用于生成一个随机的UUID,而uuid.NewString()函数用于生成一个代表UUID的字符串。这是在Go中生成UUID的标准方法。

2024-08-23



package main
 
import "fmt"
 
// 定义一个简单的结构体
type Person struct {
    Name string
    Age  int
}
 
// 定义一个方法,接收一个Person类型的参数,返回一个表示个人信息的字符串
func (p Person) Introduce() string {
    return fmt.Sprintf("你好,我是%s,今年%d岁。", p.Name, p.Age)
}
 
func main() {
    // 创建一个Person实例
    person := Person{"小明", 25}
 
    // 调用方法并打印结果
    fmt.Println(person.Introduce())
}

这段代码定义了一个名为Person的结构体,并为其添加了一个名为Introduce的方法。在main函数中,我们创建了一个Person实例,并调用了Introduce方法,打印出了小明的个人介绍。这是Golang中的基本概念,对于学习者来说很容易理解和掌握。

2024-08-23

在Go语言中,如果你想在自己的项目中使用自己开发的包(库),你可以采用以下两种方式:

  1. 使用go get命令克隆你的包到GOPATH下。
  2. 如果你的包在Github或其他代码仓库,可以直接用go get命令克隆到GOPATH下,然后在go.mod中用相对路径引用。

以下是具体的操作步骤和示例:

方法一:使用go get命令克隆你的包到GOPATH下。

首先,你需要将你的包放在一个公开的代码仓库中,如GitHub、GitLab或者Gitee。然后在你的项目目录下运行以下命令:




go get github.com/your-username/your-package

然后在你的go.mod文件中添加以下内容:




require (
    github.com/your-username/your-package v0.0.0-20190101010101-abcdefabcdef
)

方法二:如果你的包在本地,可以用以下方式引用:

首先,在你的项目目录下运行go mod init your-project-name来初始化go.mod文件。

然后,在你的go.mod文件中添加以下内容:




require (
    your-local-package v0.0.0-20190101010101-abcdefabcdef
)
replace your-local-package => ../path-to-your-local-package

其中,your-local-package是你的本地包名,../path-to-your-local-package是你的本地包相对于你的项目目录的路径。

以上两种方法都可以让你在自己的Go项目中使用自己开发的包。在实际使用中,你可以根据你的具体情况选择合适的方法。