go 解析 csv 文件报错

问题 最近在使用 go 解析 csv 文件时,读取并打印 csv 的每行内容时,读取到第11行时,程序报错,提示: record on line 11: wrong number of fields 分析 遇到这个问题,我第一反应是 csv 文件的格式有问题,于是我使用 cat 命令查看 csv 文件,发现 csv 文件的格式是正确的,没有问题。 并查看分隔符是正确的,于是可以得出 csv 文件是没有问题的。 接下来就查看所使用的标准库 encoding/csv, 通过查阅文档及 issue, 发现 csv 包中的 FieldsPerRecord 字段,FieldsPerRecord表示csv 文件每行的预期字段数, 如果为正数,则读取的每条记录都必须有对应的字段数,如果为0,则会以第一条记录的数量为标准,接下来每行都必须有对应的字段数,如果为负数,则不会检查字段数。 修改后的代码如下: package main import ( "encoding/csv" "fmt" "io" "log" "os" ) func main() { file, err := os.Open("./xx.csv") if err != nil { log.Fatal(err) } defer file.Close() // 创建一个 CSV reader reader := csv.NewReader(file) reader.FieldsPerRecord = -1 // 循环读取 CSV 文件中的每一行数据 for { record, err := reader.Read() if err == io.EOF { break } if err != nil { log.Fatal(err) } // 处理每一行数据 fmt.Println(record) fmt.Println(len(record)) } } 小结 本文记录了在使用 go 解析csv时遇到字段数不匹配的问题,并分析了问题的原因,并给出了相应的解决方法。 ...

十二月 5, 2024 · overstarry

Go Recivie Email

前言 电子邮件是现代办公和通信中不可或缺的工具,它广泛应用于数据交换和工作沟通。为了更高效地处理邮件内容,我们可以借助程序来实现自动化处理。本文将详细介绍如何使用 Go 语言来接收和处理电子邮件。 通过查阅资料,了解到可以通过 IMAP 协议来接收电子邮件,IMAP 协议是电子邮件接收协议,它允许客户端通过网络连接到邮件服务器,并从服务器上下载邮件。除了 IMAP 协议,还有 POP3 协议,POP3 协议与 IMAP 协议类似,但它在在客户端上对邮件的操作不会反馈到邮件服务器上,也就是说,在客户端的操作不会影响服务器上的邮件。当你需要从多个邮件客户端访问邮件时,IMAP 协议是一个更好的选择。 go-imap 通过对比不同的库,最后选择了 go-imap 库,它是一个基于 IMAP 协议的 Go 语言库,可以通过它构建客户端或者服务端。 安装 可以通过以下命令安装: go get github.com/emersion/go-imap 使用 我们将通过官方的例子进行切入: 先通过 DialTLS 连接对应的电子邮箱 IMAP 服务器,然后通过登录邮箱,获取所有的邮箱文件夹,最后选择收件箱,获取收件箱中最新的4封邮件,并打印没封邮件的主题。 运行代码: 2024/11/23 16:16:11 Connecting to server... 2024/11/23 16:16:11 Connected 2024/11/23 16:16:12 Logged in 2024/11/23 16:16:12 Mailboxes: 2024/11/23 16:16:13 * 其他文件夹 2024/11/23 16:16:13 * Drafts 2024/11/23 16:16:13 * Deleted Messages 2024/11/23 16:16:13 * Sent Messages 2024/11/23 16:16:13 * Junk 2024/11/23 16:16:13 * INBOX 2024/11/23 16:16:13 Flags for INBOX: [\Answered \Flagged \Deleted \Draft \Seen] 2024/11/23 16:16:13 Last 4 messages: 2024/11/23 16:16:13 * =?GBK?B?xx?= 2024/11/23 16:16:13 * =?GBK?B?xxx?= 2024/11/23 16:16:13 * =?GBK?B?xx==?= 2024/11/23 16:16:13 * =?GBK?B?xx+k=?= 2024/11/23 16:16:13 Done! 可以看到打印出来的邮件主题是乱码,通过查询资料,了解到邮件的字段是采用特殊编码的,需要进行解码。可以通过https://github.com/emersion/go-message 这个库进行解码。 ...

十一月 23, 2024 · overstarry

go-soap 简介

前言 最近需要调用一个第三方的接口进行数据的采集,这个接口是基于 SOAP 协议的,所以需要使用soap 相关的客户端进行调用。于是我调研了一些开源的 golang 的 soap 客户端,发现 go-soap 这个库的文档比较完善,而且使用起来也比较简单,所以就选择了这个库。 安装 使用以下命令进行安装: go get github.com/tiaguinho/gosoap 使用 由于目前没有特别好的例子,这里就以官方的例子进行说明。 官方的代码如下: package main import ( "encoding/xml" "log" "net/http" "time" "github.com/tiaguinho/gosoap" ) // GetIPLocationResponse will hold the Soap response type GetIPLocationResponse struct { GetIPLocationResult string `xml:"GetIpLocationResult"` } // GetIPLocationResult will type GetIPLocationResult struct { XMLName xml.Name `xml:"GeoIP"` Country string `xml:"Country"` State string `xml:"State"` } var ( r GetIPLocationResponse ) func main() { httpClient := &http.Client{ Timeout: 1500 * time.Millisecond, } soap, err := gosoap.SoapClient("http://wsgeoip.lavasoft.com/ipservice.asmx?WSDL", httpClient) if err != nil { log.Fatalf("SoapClient error: %s", err) } // Use gosoap.ArrayParams to support fixed position params params := gosoap.Params{ "sIp": "8.8.8.8", } res, err := soap.Call("GetIpLocation", params) if err != nil { log.Fatalf("Call error: %s", err) } res.Unmarshal(&r) // GetIpLocationResult will be a string. We need to parse it to XML result := GetIPLocationResult{} err = xml.Unmarshal([]byte(r.GetIPLocationResult), &result) if err != nil { log.Fatalf("xml.Unmarshal error: %s", err) } if result.Country != "US" { log.Fatalf("error: %+v", r) } log.Println("Country: ", result.Country) log.Println("State: ", result.State) } 可以看到 go-soap的使用跟常规的 http client的使用方法类似,都是创建一个连接,准备方法的参数,然后调用相应的方法。 这段代码展示了如何使用 go-soap 库连接 SOAP 服务、发送请求、处理响应,以及如何解析 XML 格式的返回数据。 ...

十月 4, 2024 · overstarry

go humanize介绍

前言 今天在 Github 查看一些开源项目时,发现了一个"人性化"的项目 go-humanize,此项目可以将一些常见的容量、时间、千分位转换为人们可以理解的形式,例如一个文件大小是 2000000 bytes,我们不能很好的理解,但如果告诉你是 2mb,我们就能很好的理解了。 go-humanize 就是方便的将一些不太能快速理解的数字转换为人们可以理解的形式。 安装 使用以下命令安装: go get github.com/dustin/go-humanize 使用 接下来分别介绍一些常见的功能。 容量转换 现在我们有一个文件大小是 52854982 bytes,我们使用 humanize 包的 Bytes 方法将其转换为人们可以理解的形式 53MB,也可以使用IBytes方法转换为MIB单位的值。也可以使用ParseBytes方法将可以理解的形式转换为bytes单位的值。 fmt.Printf("That file is %s.\n", humanize.IBytes(52854982)) fmt.Printf("That file is %s.", humanize.Bytes(52854982)) 时间转换 时间转换与容量转换类型,使用方法十分类似,使用方法如下: t := time.Now().Add(time.Hour * -7) fmt.Printf("This was touched %s.", humanize.Time(t)) //This was touched 7 hours ago. Time 根据相对时间转换为人们可以理解的形式,例如: xx天之前、xx小时之后等形式。 千分位转换 如果我们想在数字中添加逗号,就可以使用 Comma 方法,例如在处理金额时,我们通常会使用逗号将数字分隔开,例如 1,000,000,000 fmt.Printf("num is %s.", humanize.Comma(1000000000)) 还可以使用 Commaf 方法将浮点数转换为千分位形式。 位序 在日常使用中,我们有时需要表示位序例如 1st、2nd、3rd、4th 等,humanize 包也提供了相应的功能。 fmt.Printf("num is %s.", humanize.Ordinal(1000000000)) 简单看了下源码,发现函数十分简单: func Ordinal(x int) string { suffix := "th" switch x % 10 { case 1: if x%100 != 11 { suffix = "st" } case 2: if x%100 != 12 { suffix = "nd" } case 3: if x%100 != 13 { suffix = "rd" } } return strconv.Itoa(x) + suffix } 小结 本文介绍了 go-humanize 包的一些使用方法,可以方便的将一些数字转换为人们可以理解的形式。go-humanize 还有一些格式化的函数,感兴趣的读者可以自行查看源码。 ...

八月 10, 2024 · overstarry

katana 新一代的爬虫工具

katana 介绍 katana是一款强大的新一代的网络爬虫工具,通过使用 katana ,用户能够快速的进行互联网资源的爬取和渗透测试阶段的收集任务。 特点 katana 有以下特点: 快速及高可配置的网络爬虫 标准及无头模式 主动和被动模式 JavaScript 脚本爬取解析 定制的表单内容自动填充 爬取范围控制 可自定义设置输出字段 输入数据 支持标准输入(STDIN),URL和列表(LIST) 输出数据 支持STDOUT、文件和JSON格式 安装 接下来介绍如何安装 katana katana 的安装需要 go1.18版本以上,可以执行以下命令或下载Github 仓库的发布版本。 go install github.com/projectdiscovery/katana/cmd/katana@latest windows 在安装中可能会遇到以下报错: github.com/smacker/go-tree-sitter/javascript: build constraints exclude all Go files in C:\Users\overstarry\go\pkg\mod\github.com\smacker\[email protected]\javascript # github.com/smacker/go-tree-sitter go\pkg\mod\github.com\smacker\[email protected]\iter.go:17:18: undefined: Node go\pkg\mod\github.com\smacker\[email protected]\iter.go:21:21: undefined: Node go\pkg\mod\github.com\smacker\[email protected]\iter.go:25:20: undefined: Node go\pkg\mod\github.com\smacker\[email protected]\iter.go:30:26: undefined: Node go\pkg\mod\github.com\smacker\[email protected]\iter.go:34:20: undefined: Node go\pkg\mod\github.com\smacker\[email protected]\iter.go:38:32: undefined: Node go\pkg\mod\github.com\smacker\[email protected]\iter.go:43:9: undefined: Node go\pkg\mod\github.com\smacker\[email protected]\iter.go:46:18: undefined: Node go\pkg\mod\github.com\smacker\[email protected]\iter.go:68:40: undefined: Node 可以使用以下命令解决: ...

六月 29, 2024 · overstarry

golang 生成 slug 字符串

slug 介绍 slug 在不同的场景有不同的意义,在 URL 中表示一种用于描述资源的短简洁易于理解的资源描述符,在数据库系统中还可以用于描述资源的唯一标识符,总的来说 slug 可以用来标识和描述资源的文本标识符,有很好的可读性和唯一性。 本文将介绍 golang 中如何根据字符串生成相应的 slug 文本。 安装 执行 go get -u github.com/gosimple/slug 来安装 slug 使用 先介绍 slug 库的基础使用方法: package main import ( "fmt" "github.com/gosimple/slug" ) func main() { text := slug.Make("overstarry home") fmt.Println(text) text = slug.Make("text generate") fmt.Println(text) } 运行后: overstarry-home text-generate 除了基础的转换功能,slug 还支持将不同的语言进行转换,查看下面的例子: func main() { text := slug.Make("overstarry home") fmt.Println(text) text = slug.Make("text generate") fmt.Println(text) text = slug.Make("Hellö Wörld хелло ворлд") fmt.Println(text) someText := slug.Make("影師") fmt.Println(someText) enText := slug.MakeLang("This & that", "en") fmt.Println(enText) } overstarry-home text-generate hello-world-khello-vorld ping-guo this-and-that 如果想要保留大写字母,可以设置 slug.Lowercase 参数来实现。如果想实现自定义的替换可以使用 slug.CustomSub 来实现。 ...

五月 25, 2024 · overstarry

Go 生成 Google analytics 衡量ID

Google Analytics 介绍 Google Analytics(分析)4 是一项分析服务,用于衡量您的网站和应用中的流量和互动情况。本文将介绍如何通过调用 Google Analytics admin API来生成 Google Analytics 衡量ID. 配置 启用API 在 Google Cloud console 后台 API 和服务 启用 Google Analytics Admin API。 配置服务账号 为了调用API,我们需要创建一个服务账号,然后为创建的服务账号添加密钥。 需要注意的是还需要在 Google Analytics 为服务账号添加权限,不然请求接口会没数据。 安装 go客户端 接下来安装go客户端: go get google.golang.org/api/analyticsadmin/v1alpha 生成流程 接下来我们会按照常规的 id 生成流程编写相应的代码,流程: 1 获取账号信息 通过 List 接口获取当前服务账号所拥有的所有 Google Analytics 账户信息。 accountsService := analyticsadmin.NewAccountsService(service) accountsReply, err := accountsService.List().Do(); if err != nil { log.Fatal("list account err",err) return } for _,acc := range accountsReply.Accounts { fmt.Println(acc.Name) } 2 创建媒体资源 ...

四月 18, 2024 · overstarry

go 汉字转拼音 go-pinyin

前言 本文介绍一个 go 汉字转拼音的库 go-pinyin,可以从名字看出这个库的功能就是将汉字转换为相应的拼音。接下来就由我来简单的介绍 go-pinyin 。 安装 使用此命令安装: go get github.com/mozillazg/go-pinyin cli 安装 如果你的 go 版本在 1.17 以下使用此命令安装: go get -u github.com/mozillazg/go-pinyin/cli/pinyin。1.17及以上版本使用此命令安装:go install github.com/mozillazg/go-pinyin/cli/pinyin@latest。 使用 接下来将分别介绍 cli 的使用和 API 的使用。 cli 使用 安装完在终端输入 pinyin,可以看到使用的方法,尝试一个汉字,可以看到相应的拼音,但也可以看出对多音字的支持有问题。 $ pinyin 中国 zhōng guó $ pinyin 重庆 zhòng qìng 接下来介绍 API 的使用。 api 使用 通过查看文档,可以看出主要是2个方法 pinyin.NewArgs 和 pinyin.Pinyin 。 pinyin.NewArgs 创建包含默认配置的 Args, 可以通过修改 Args 的成员来使用不同的模式。 type Args struct { Style int // 拼音风格(默认: Normal) Heteronym bool // 是否启用多音字模式(默认:禁用) Separator string // Slug 中使用的分隔符(默认:-) // 处理没有拼音的字符(默认忽略没有拼音的字符) // 函数返回的 slice 的长度为0 则表示忽略这个字符 Fallback func(r rune, a Args) []string } pinyin.Pinyin 就是将汉字转为拼音。 ...

十二月 23, 2023 · overstarry

mergo 介绍

前言 今天介绍一个 go 库 - mergo, mergo 用来方便的合并 struct 和 map ,可以将结构体的字段赋值到map中,可以将map的值赋值给结构体的字段. Mergo 通过在零值字段中设置默认值来合并同类型的struct 和 map。Mergo 不会合并未导出(私有)字段。它会递归合并任何已导出的字段。它也不会合并map中的结构体(因为它们无法使用 Go 反射寻址)。 Mergo 在很多知名项目中被使用,如 containerd、k8s、loki等。 安装 使用以下命令安装 mergo : go get -u dario.cat/mergo 使用 接下来介绍 mergo 的基础使用和高级用法。 基础使用 mergo 提供了2个主要函数: Merge和Map, Mergo 用来合并2个相同结构的 struct 和 map, Map 用来在结构和map之间赋值。 例子: package main import ( "fmt" "log" "github.com/imdario/mergo" ) type redisConfig struct { Address string Port int DB int UserName string PassWord string } var defaultConfig = redisConfig{ Address: "127.0.0.1", Port: 6379, DB: 1, UserName: "123", PassWord: "123", } func main() { var config redisConfig if err := mergo.Merge(&config, defaultConfig); err != nil { log.Fatal(err) } fmt.Println("redis address: ", config.Address) fmt.Println("redis port: ", config.Port) fmt.Println("redis db: ", config.DB) fmt.Println("redis username: ", config.UserName) fmt.Println("redis password: ", config.PassWord) var m = make(map[string]interface{}) if err := mergo.Map(&m, defaultConfig); err != nil { log.Fatal(err) } fmt.Println(m) } 接下来介绍一些高级用法: ...

十二月 16, 2023 · overstarry

conc 一个更好的go并发库

前言 本文介绍 conc - 一个更好的 go 并发库, sourcegraph 在日常开发中使用go原生并发出现了问题,由此开发了 conc ,相比标准并发代码更优雅,代码更少,下面展示一个例子,可以看出代码减少了许多. type propagatedPanic struct { val any stack []byte } func main() { done := make(chan *propagatedPanic) go func() { defer func() { if v := recover(); v != nil { done <- &propagatedPanic{ val: v, stack: debug.Stack(), } } else { done <- nil } }() doSomethingThatMightPanic() }() if val := <-done; val != nil { panic(val) } } // conc func main() { var wg conc.WaitGroup wg.Go(doSomethingThatMightPanic) // panics with a nice stacktrace wg.Wait() } 安装 使用以下命令进行安装: go get github.com/sourcegraph/conc ...

十二月 9, 2023 · overstarry