在Go语言中处理带BOM的json数据

缘起 今天开发的时候遇到一个奇怪的问题,一个JSON文件,使用文本编辑器打开复制,并使用strings.NewReader来decode,是正常的,但是通过文件打开同样调用的方法来decode,却是失败的。后面通过打开IDE,发现文件前面有一些空白的内容。是一些bom信息。 关于BOM BOM (Byte Order Mark) 的历史原因和用途主要与字符编码和跨平台兼容性有关: 历史原因 Unicode 出现前: ASCII 只用 1 字节,没有字节序问题 各国有自己的编码标准(GB2312、Shift-JIS等) Unicode 引入后: UTF-16 使用 2 字节表示字符 不同CPU架构的字节序不同: Big Endian (大端序): 高位字节在前 Little Endian (小端序): 低位字节在前 跨平台问题: Intel x86 使用小端序 Motorola 68k 使用大端序 同一文件在不同平台解析可能出错 BOM 的作用 UTF-16 的字节序标记: FE FF: Big Endian FF FE: Little Endian UTF-8 的编码标识: EF BB BF: 表明这是 UTF-8 编码 UTF-8 实际不需要 BOM(字节序无关) Windows 添加 BOM 主要为了兼容性 实际例子 // 字符 "中" 在不同编码下的表示 text := "中" // UTF-8: E4 B8 AD // UTF-16BE: 4E 2D // UTF-16LE: 2D 4E // 示例代码 func showEncoding() { text := "中" utf8Bytes := []byte(text) // UTF-8 utf16beBytes := utf16....

Connect Rpc快速上手

入门 Connect RPC 是一个轻量级的 HTTP API 构建库,支持浏览器和 gRPC 兼容的 API。它通过 Protocol Buffer 定义服务,并生成类型安全的服务器和客户端代码。 压缩和序列化 Connect 支持多种压缩和序列化选项,默认情况下,Connect 处理程序支持在默认压缩级别使用标准库的 compress/gzip 进行 gzip 压缩。Connect 客户端默认发送未压缩的请求并请求 gzip 压缩的响应。如果您知道服务器支持 gzip,则还可以在客户端构建期间使用 WithSendGzip 选项来压缩请求。 // 服务端不需要进行什么选项设置 参考https://github.com/connectrpc/connect-go/issues/773 handler := greetv1connect.NewGreetServiceHandler( &GreetServer{}, ) // 客户端配置压缩,默认 client := greetv1connect.NewGreetServiceClient( http.DefaultClient, "http://localhost:8080", connect.WithSendGzip(), ) 自定义压缩实现: type CustomCompressor struct{} func (c *CustomCompressor) Name() string { return "custom" } func (c *CustomCompressor) Compress(w io.Writer) (io.WriteCloser, error) func (c *CustomCompressor) Decompress(r io.Reader) (io.Reader, error) Get 请求 Connect 支持通过 HTTP GET 进行无副作用的请求,这使得可以在浏览器、CDN 或代理中缓存某些类型的请求。...

Go Ble开发实战

⚠️代码仅最后部分进行了测试,前面的暂未测试 1. 简介 BLE (Bluetooth Low Energy) 是一种低功耗蓝牙技术。Go-BLE 是 Go 语言的 BLE 库,提供了简单易用的 API 来开发 BLE 应用。本文将通过一个完整的示例来展示如何使用 Go-BLE 创建一个蓝牙服务器。 Go-BLE 主要支持 Linux 和 macOS 平台(1),但需要注意 macOS 部分目前并未被积极维护。 2. 环境准备 2.1 安装依赖 # 安装 go-ble go get -u github.com/go-ble/ble # 安装设备支持库 go get -u github.com/go-ble/ble/examples/lib/dev # Linux系统需要设置权限 sudo setcap 'cap_net_raw,cap_net_admin+eip' ./your_program 3. BLE基础概念 3.1 核心概念 Peripheral (外围设备):提供服务的设备 Central (中心设备):连接外围设备的设备(如手机) Service (服务):功能的集合 Characteristic (特征):具体的数据点 Descriptor (描述符):特征的元数据 3.2 常见的 UUID 标准服务 UUID: 电池服务:0x180F 设备信息服务:0x180A 心率务:0x180D 标准特征 UUID: 电池电量:0x2A19 设备名称:0x2A00 制造商名称:0x2A29 型号名称:0x2A24 序列号:0x2A25 固件版本:0x2A26 信号强度:0x2A1C 自定义 UUID 生成: // 使用在线工具生成 UUID v4 svcUUID := ble....

使用 Suture在Go中实现可靠的监督树

简介 在构建复杂的分布式系统时,我们常常需要面对各种意外情况,如服务崩溃、网络中断等。为了提高系统的可靠性和容错能力,监督树模式应运而生。Suture 是一个受 Erlang OTP 框架启发的 Go 语言监督树库,它为 Go 开发者提供了一种优雅的方式来管理和监控长时间运行的服务。 监督树的核心思想是将系统组织成一个树状结构,其中父节点(监督者)负责监控和管理子节点(工作者)。当子节点发生故障时,父节点可以根据预定策略进行重启或其他恢复操作,从而提高系统的整体稳定性。 Suture 的核心概念 Suture 的设计围绕以下几个核心概念: Service 接口: 定义了可被监督的服务应该实现的方法。 Supervisor 结构体: 代表一个监督者,负责管理一组服务。 重启策略: 定义了当服务失败时,监督者应该如何响应。 安装和基本使用 首先,通过以下命令安装 Suture: go get github.com/thejerf/suture/v4 然后,在你的 Go 代码中导入 Suture: import "github.com/thejerf/suture/v4" 创建一个简单的 Service: type MyService struct{} var _ suture.Service = (*MyService)(nil) func (s *MyService) Serve(ctx context.Context) error { for { select { case <-ctx.Done(): return nil default: // 执行服务逻辑 time.Sleep(time.Second) fmt.Println("Service is running") } } } 设置 Supervisor 并添加 Service:...

在go中使用CoAP

CoAP协议 CoAP(Constrained Application Protocol)是一种专为物联网(IoT)和受限环境设计的网络协议。它的主要目标是为资源受限的设备(如传感器、执行器等)提供一种轻量级的通信方式。以下是 CoAP 协议的几个关键特点和功能: 1. 轻量级设计 小开销:CoAP 使用 UDP(用户数据报协议)作为传输层,相比于 TCP(传输控制协议),它具有更小的头部开销,适合带宽有限的环境。 简化的消息格式:CoAP 消息格式简单,适合资源受限的设备。 2. 请求/响应模型 类似 HTTP:CoAP 采用类似于 HTTP 的请求/响应模型,客户端可以发送请求(如 GET、POST、PUT、DELETE)来与服务器交互。 资源导向:CoAP 允许客户端访问和操作服务器上的资源,资源通过 URI(统一资源标识符)进行标识。 3. 可靠性 确认机制:虽然 CoAP 基于 UDP,但它实现了可靠性机制,包括重传和确认,以确保消息的可靠传输。 非确认和确认消息:CoAP 支持两种类型的消息:确认消息(需要确认)和非确认消息(不需要确认),以适应不同的应用需求。 4. 观察功能 资源观察:CoAP 支持观察功能,允许客户端订阅资源的变化,当资源状态发生变化时,服务器会主动通知客户端。这减少了轮询请求的需要。 5. 多播支持 多播通信:CoAP 原生支持多播,允许服务器向多个客户端同时发送消息,适合需要广播信息的场景。 6. 安全性 DTLS:CoAP 可以与 DTLS(Datagram Transport Layer Security)结合使用,以提供数据加密和安全性,保护数据在传输过程中的安全。 应用场景 物联网:CoAP 广泛应用于物联网设备的通信,如智能家居、环境监测、工业自动化等。 资源受限设备:适合用于低功耗、低带宽的设备和网络环境。 在go中使用coap echo服务 server: package main import ( "fmt" "log" "github.com/plgd-dev/go-coap/v3" "github.com/plgd-dev/go-coap/v3/message" "github.com/plgd-dev/go-coap/v3/message/codes" "github.com/plgd-dev/go-coap/v3/mux" ) func main() { r := mux....

一些docker和k8s的笔记

常见的项目Dockerfile golang项目 # 构建阶段 FROM golang:1.23 AS builder # 设置工作目录, WORKDIR /app # 复制go.mod和go.sum文件 COPY go.mod go.sum ./ # 设置goproxy RUN go env -w GOPROXY='https://goproxy.io,https://goproxy.cn,direct' # 下载依赖 RUN go mod download # 复制源代码 COPY . . # 构建应用 RUN CGO_ENABLED=0 GOOS=linux go build -o server . # 运行阶段 FROM alpine:latest # 安装ca-certificates以支持HTTPS, RUN apk --no-cache add ca-certificates WORKDIR /root/ # 从构建阶段复制编译好的二进制文件 COPY --from=builder /app/server . # 暴露端口(如果您的应用监听某个端口) EXPOSE 8080 # 运行应用 CMD ["....

转换数字到Excel列字母实现

根据微软官方文档,excel最大支持1,048,576 行, 16,384 列。下面的代码并未处理这一限制。 Rust 实现代码: fn convert_to_title(mut n: i32) -> String { let mut result = String::new(); while n != 0 { n -= 1; let letter = (n % 26) as u8 + b'A'; result.insert(0, letter as char); n /= 26; } result } #[test] fn test_convert_to_title() { let aa = convert_to_title(27); assert_eq!(aa, "AC"); } Go 实现代码: func convertToTitle(n int) string { result := "" for n > 0 { n-- letter := n%26 result = string('A'+letter) + result n /= 26 } return result } C# 实现代码:...

一些使用go-fyne的笔记

界面交互 中文字体设置 查阅相关资料,有下面几种解决方案,下面来依次说明。 环境变量 可以通过指定 FYNE_FONT 环境变量来使用替代字体 使用字体bundle 安装fyne工具,使用下面的命令: go install fyne.io/fyne/v2/cmd/fyne@latest 准备好要使用的字体,我们这里使用miSans,使用下面命令 fyne bundle MiSans-Normal.ttf > bundle.go 然后创建一个theme package tinytheme import ( "fyne.io/fyne/v2" "fyne.io/fyne/v2/theme" "fyneHello/fontRes" "image/color" ) type ChineseTheme struct{} var _ fyne.Theme = (*ChineseTheme)(nil) func (m *ChineseTheme) Font(s fyne.TextStyle) fyne.Resource { return fontRes.ResourceMiSansTTF } func (*ChineseTheme) Color(n fyne.ThemeColorName, v fyne.ThemeVariant) color.Color { return theme.DefaultTheme().Color(n, v) } func (*ChineseTheme) Icon(n fyne.ThemeIconName) fyne.Resource { return theme.DefaultTheme().Icon(n) } func (*ChineseTheme) Size(n fyne....

Rxgo使用备忘录

官网文档 –机器翻译内容– 介绍 ReactiveX,简称 Rx,是一个用于使用 Observable 流进行编程的 API。 RxGo 实现基于管道的概念。管道是由通道连接的一系列阶段,其中每个阶段是一组运行相同功能的 goroutine。 让我们看一个具体的例子,每个框都是一个运算符: 我们使用 Just 运算符基于固定的项目列表创建一个静态 Observable。 我们使用 Map 运算符定义一个转换函数(将圆形转换为方形)。 我们使用 Filter 运算符过滤每个黄色方块。 在此示例中,最终物品在通道中发送,可供消费者使用。使用 RxGo 消费或生成数据的方法有很多种。在频道中发布结果只是其中之一。 每个算子都是一个转换阶段。默认情况下,一切都是顺序的。然而,我们可以通过定义同一运算符的多个实例来利用现代 CPU 架构。每个运算符实例都是连接到公共通道的 goroutine。 RxGo 的理念是实现 ReactiveX 概念并利用主要的 Go 原语(通道、goroutines 等),以便两个世界之间的集成尽可能顺利。 安装 RxGo v2 go get -u github.com/reactivex/rxgo/v2 入门 你好世界 让我们创建第一个 Observable 并使用一个项目: observable := rxgo.Just("Hello, World!")() ch := observable.Observe() item := <-ch fmt.Println(item.V) Just 运算符从静态项目列表创建一个 Observable。 Of(value) 根据给定值创建一个项目。如果我们想从错误中创建一个项目,我们必须使用 Error(err) 。这与 v1 不同,v1 直接接受值或错误而无需包装它。这一改变的理由是什么?它是为了(希望)Go 2 中的泛型功能为 RxGo 做好准备。...