将Go的io字符串转换为int类型的Atoi无效参数

huangapple go评论127阅读模式
英文:

Go io string to int Atoi invalid argument

问题

我正在尝试在Go语言中解析来自WebSockets连接的字符串。我正在实现连接的两端,因此数据格式的规范仅取决于我自己。

由于这是一个简单的应用程序(主要用于学习目的),我想出了ActionId Data的格式,其中ActionId是一个uint8类型。BackendHandler是WebSocket连接中每个请求的处理程序。

平台信息

  1. kuba:~$ echo {$GOARCH,$GOOS,`6g -V`}
  2. amd64 linux 6g version release.r60.3 9516

代码:

  1. const ( // 指定ActionId
  2. SabPause = iota
  3. )
  4. func BackendHandler(ws *websocket.Conn) {
  5. buf := make([]byte, 512)
  6. _, err := ws.Read(buf)
  7. if err != nil { panic(err.String()) }
  8. str := string(buf)
  9. tmp, _ := strconv.Atoi(str[:0])
  10. data := str[2:]
  11. fmt.Println(tmp, data)
  12. switch tmp {
  13. case SabPause:
  14. // 在将“0 2”传递给WebSocket连接时,我得到“parsing "2": invalid argument”错误
  15. minutes, ok := strconv.Atoui(data)
  16. if ok != nil {
  17. panic(ok.String())
  18. }
  19. PauseSab(uint8(minutes))
  20. default:
  21. panic("BackendHandler的输入不匹配")
  22. }
  23. }

所有的输出:(注意我用于检查的Println)

  1. 0 2
  2. panic: parsing "2": invalid argument [recovered]
  3. panic: runtime error: invalid memory address or nil pointer dereference

我找不到导致此错误的代码,只能找到错误代码的定义(依赖于平台)。我希望能得到改进代码的一般想法,但主要是我想解决转换问题。

这与我的缓冲区->字符串转换和切片操作有关吗(我不想使用SplitAfter方法)?

编辑

以下代码重现了这个问题:

  1. package main
  2. import (
  3. "strconv"
  4. "io/ioutil"
  5. )
  6. func main() {
  7. buf , _ := ioutil.ReadFile("input")
  8. str := string(buf)
  9. _, ok := strconv.Atoui(str[2:])
  10. if ok != nil {
  11. panic(ok.String())
  12. }
  13. }

文件input必须包含0 2\r\n(根据文件结尾的不同,其他操作系统上可能会有所不同)。可以通过为重新切片添加结束索引来修复此代码,如下所示:

  1. _, ok := strconv.Atoui(str[2:3])
英文:

I'm trying to parse a string from WebSockets connection in Go language. I'm implementing both sides of the connection, so the specification of data format is depending only on me.

As this is a simple app (generally for learning purposes), I've come up with ActionId Data, where ActionId is a uint8. BackendHandler is a handler for every request in WebSocket Connection.

Platform information

  1. kuba:~$ echo {$GOARCH,$GOOS,`6g -V`}
  2. amd64 linux 6g version release.r60.3 9516

code:

  1. const ( // Specifies ActionId's
  2. SabPause = iota
  3. )
  4. func BackendHandler(ws *websocket.Conn) {
  5. buf := make([]byte, 512)
  6. _, err := ws.Read(buf)
  7. if err != nil { panic(err.String()) }
  8. str := string(buf)
  9. tmp, _ := strconv.Atoi(str[:0])
  10. data := str[2:]
  11. fmt.Println(tmp, data)
  12. switch tmp {
  13. case SabPause:
  14. // Here I get `parsing "2": invalid argument`
  15. // when passing "0 2" to websocket connection
  16. minutes, ok := strconv.Atoui(data)
  17. if ok != nil {
  18. panic(ok.String())
  19. }
  20. PauseSab(uint8(minutes))
  21. default:
  22. panic("Unmatched input for BackendHandler")
  23. }
  24. }

All the output: (note the Println that I used for inspecting)

  1. 0 2
  2. panic: parsing "2": invalid argument [recovered]
  3. panic: runtime error: invalid memory address or nil pointer dereference

I couldn't find the code from which this error is launch, only where the error code is defined (dependent on platform). I'd appreciate general ideas for improving my code, but mainly I just want to solve the conversion problem.

Is this related to my buffer -> string conversion and slice-manipulation(I didn't want to use SplitAfter methods)?

Edit

This code reproduces the problem:

  1. package main
  2. import (
  3. "strconv"
  4. "io/ioutil"
  5. )
  6. func main() {
  7. buf , _ := ioutil.ReadFile("input")
  8. str := string(buf)
  9. _, ok := strconv.Atoui(str[2:])
  10. if ok != nil {
  11. panic(ok.String())
  12. }
  13. }

The file input has to contain 0 2\r\n (depending on the file ending, it may look different on other OSes). This code can be fixed by adding the ending index for reslice, this way:

  1. _, ok := strconv.Atoui(str[2:3])

答案1

得分: 1

你没有提供一个小的可编译和可运行的程序来说明你的问题。你也没有提供完整和有意义的打印诊断信息。

我最好的猜测是你有一个C风格的以null结尾的字符串。例如,简化你的代码,

  1. package main
  2. import (
  3. "fmt"
  4. "strconv"
  5. )
  6. func main() {
  7. buf := make([]byte, 512)
  8. buf = []byte("0 2\x00") // 测试数据
  9. str := string(buf)
  10. tmp, err := strconv.Atoi(str[:0])
  11. if err != nil {
  12. fmt.Println(err)
  13. }
  14. data := str[2:]
  15. fmt.Println("tmp:", tmp)
  16. fmt.Println("str:", len(str), ";", str, ";", []byte(str))
  17. fmt.Println("data", len(data), ";", data, ";", []byte(data))
  18. // 这里当将"0 2"传递给websocket连接时,我得到了`parsing "2": invalid argument`
  19. minutes, ok := strconv.Atoui(data)
  20. if ok != nil {
  21. panic(ok.String())
  22. }
  23. _ = minutes
  24. }

输出:

  1. parsing "": invalid argument
  2. tmp: 0
  3. str: 4 ; 0 2 ; [48 32 50 0]
  4. data 2 ; 2 ; [50 0]
  5. panic: parsing "2": invalid argument
  6. runtime.panic+0xac /home/peter/gor/src/pkg/runtime/proc.c:1254
  7. runtime.panic(0x4492c0, 0xf840002460)
  8. main.main+0x603 /home/peter/gopath/src/so/temp.go:24
  9. main.main()
  10. runtime.mainstart+0xf /home/peter/gor/src/pkg/runtime/amd64/asm.s:78
  11. runtime.mainstart()
  12. runtime.goexit /home/peter/gor/src/pkg/runtime/proc.c:246
  13. runtime.goexit()
  14. ----- goroutine created by -----
  15. _rt0_amd64+0xc9 /home/peter/gor/src/pkg/runtime/amd64/asm.s:65

如果你在你的代码中添加我的打印诊断语句,你会看到什么?

请注意,你的tmp, _ := strconv.Atoi(str[:0])语句可能是错误的,因为str[:0]等同于str[0:0],它等同于空的字符串""

我怀疑你的问题是你忽略了ws.Readn返回值。例如(包括诊断信息),我期望看到:

  1. buf := make([]byte, 512)
  2. buf = buf[:cap(buf)]
  3. n, err := ws.Read(buf)
  4. if err != nil {
  5. panic(err.String())
  6. }
  7. fmt.Println(len(buf), n)
  8. buf = buf[:n]
  9. fmt.Println(len(buf), n)

另外,尝试使用以下代码来设置tmp

  1. tmp, err := strconv.Atoi(str[:1])
  2. if err != nil {
  3. panic(err.String())
  4. }
英文:

You didn't provide a small compilable and runnable program to illustrate your problem. Nor did you provide full and meaningful print diagnostic messages.

My best guess is that you have a C-style null-terminated string. For example, simplifying your code,

  1. package main
  2. import (
  3. "fmt"
  4. "strconv"
  5. )
  6. func main() {
  7. buf := make([]byte, 512)
  8. buf = []byte("0 2\x00") // test data
  9. str := string(buf)
  10. tmp, err := strconv.Atoi(str[:0])
  11. if err != nil {
  12. fmt.Println(err)
  13. }
  14. data := str[2:]
  15. fmt.Println("tmp:", tmp)
  16. fmt.Println("str:", len(str), ";", str, ";", []byte(str))
  17. fmt.Println("data", len(data), ";", data, ";", []byte(data))
  18. // Here I get `parsing "2": invalid argument`
  19. // when passing "0 2" to websocket connection
  20. minutes, ok := strconv.Atoui(data)
  21. if ok != nil {
  22. panic(ok.String())
  23. }
  24. _ = minutes
  25. }

Output:

  1. parsing "": invalid argument
  2. tmp: 0
  3. str: 4 ; 0 2 ; [48 32 50 0]
  4. data 2 ; 2 ; [50 0]
  5. panic: parsing "2": invalid argument
  6. runtime.panic+0xac /home/peter/gor/src/pkg/runtime/proc.c:1254
  7. runtime.panic(0x4492c0, 0xf840002460)
  8. main.main+0x603 /home/peter/gopath/src/so/temp.go:24
  9. main.main()
  10. runtime.mainstart+0xf /home/peter/gor/src/pkg/runtime/amd64/asm.s:78
  11. runtime.mainstart()
  12. runtime.goexit /home/peter/gor/src/pkg/runtime/proc.c:246
  13. runtime.goexit()
  14. ----- goroutine created by -----
  15. _rt0_amd64+0xc9 /home/peter/gor/src/pkg/runtime/amd64/asm.s:65

If you add my print diagnostic statements to your code, what do you see?

Note that your tmp, _ := strconv.Atoi(str[:0]) statement is probably wrong, since str[:0] is equivalent to str[0:0], which is equivalent to the empty string "".

I suspect that your problem is that you are ignoring the n return value from ws.Read. For example (including diagnostic messages), I would expect,

  1. buf := make([]byte, 512)
  2. buf = buf[:cap(buf)]
  3. n, err := ws.Read(buf)
  4. if err != nil {
  5. panic(err.String())
  6. }
  7. fmt.Println(len(buf), n)
  8. buf = buf[:n]
  9. fmt.Println(len(buf), n)

Also, try using this code to set tmp,

  1. tmp, err := strconv.Atoi(str[:1])
  2. if err != nil {
  3. panic(err.String())
  4. }

huangapple
  • 本文由 发表于 2012年2月11日 19:58:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/9240008.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定