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

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

Go io string to int Atoi invalid argument

问题

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

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

平台信息

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

代码:

const ( // 指定ActionId
  SabPause = iota
)

func BackendHandler(ws *websocket.Conn) {
  buf := make([]byte, 512)
  _, err := ws.Read(buf)
  if err != nil { panic(err.String()) }
  str := string(buf)
  tmp, _ := strconv.Atoi(str[:0])
  data := str[2:]
  fmt.Println(tmp, data)
  switch tmp {
    case SabPause:
      // 在将“0 2”传递给WebSocket连接时,我得到“parsing "2": invalid argument”错误
      minutes, ok := strconv.Atoui(data)
      if ok != nil {
        panic(ok.String())
      }
      PauseSab(uint8(minutes))
    default:
      panic("BackendHandler的输入不匹配")
  }
}

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

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

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

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

编辑

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

package main

import (
  "strconv"
  "io/ioutil"
)

func main() {
  buf , _ := ioutil.ReadFile("input")
  str := string(buf)
  _, ok := strconv.Atoui(str[2:])
  if ok != nil {
    panic(ok.String())
  }
}

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

_, 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

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

code:

const ( // Specifies ActionId's
  SabPause = iota
)

func BackendHandler(ws *websocket.Conn) {
  buf := make([]byte, 512)
  _, err := ws.Read(buf)
  if err != nil { panic(err.String()) }
  str := string(buf)
  tmp, _ := strconv.Atoi(str[:0])
  data := str[2:]
  fmt.Println(tmp, data)
  switch tmp {
    case SabPause:
      // Here I get `parsing "2": invalid argument`
      // when passing "0 2" to websocket connection
      minutes, ok := strconv.Atoui(data)
      if ok != nil {
        panic(ok.String())
      }
      PauseSab(uint8(minutes))
    default:
      panic("Unmatched input for BackendHandler")
  }
}

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

0 2
panic: parsing "2": invalid argument [recovered]
    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:

package main

import (
  "strconv"
  "io/ioutil"
)

func main() {
  buf , _ := ioutil.ReadFile("input")
  str := string(buf)
  _, ok := strconv.Atoui(str[2:])
  if ok != nil {
    panic(ok.String())
  }
}

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:

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

答案1

得分: 1

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

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

package main

import (
	"fmt"
	"strconv"
)

func main() {
	buf := make([]byte, 512)
	buf = []byte("0 2\x00") // 测试数据
	str := string(buf)
	tmp, err := strconv.Atoi(str[:0])
	if err != nil {
		fmt.Println(err)
	}
	data := str[2:]
	fmt.Println("tmp:", tmp)
	fmt.Println("str:", len(str), ";", str, ";", []byte(str))
	fmt.Println("data", len(data), ";", data, ";", []byte(data))
	// 这里当将"0 2"传递给websocket连接时,我得到了`parsing "2": invalid argument`
	minutes, ok := strconv.Atoui(data)
	if ok != nil {
		panic(ok.String())
	}
	_ = minutes
}

输出:

parsing "": invalid argument
tmp: 0
str: 4 ; 0 2 ; [48 32 50 0]
data 2 ; 2 ; [50 0]
panic: parsing "2": invalid argument

runtime.panic+0xac /home/peter/gor/src/pkg/runtime/proc.c:1254
	runtime.panic(0x4492c0, 0xf840002460)
main.main+0x603 /home/peter/gopath/src/so/temp.go:24
	main.main()
runtime.mainstart+0xf /home/peter/gor/src/pkg/runtime/amd64/asm.s:78
	runtime.mainstart()
runtime.goexit /home/peter/gor/src/pkg/runtime/proc.c:246
	runtime.goexit()
----- goroutine created by -----
_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返回值。例如(包括诊断信息),我期望看到:

buf := make([]byte, 512)
buf = buf[:cap(buf)]
n, err := ws.Read(buf)
if err != nil {
    panic(err.String())
}
fmt.Println(len(buf), n)
buf = buf[:n]
fmt.Println(len(buf), n)

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

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

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,

package main

import (
	"fmt"
	"strconv"
)

func main() {
	buf := make([]byte, 512)
	buf = []byte("0 2\x00") // test data
	str := string(buf)
	tmp, err := strconv.Atoi(str[:0])
	if err != nil {
		fmt.Println(err)
	}
	data := str[2:]
	fmt.Println("tmp:", tmp)
	fmt.Println("str:", len(str), ";", str, ";", []byte(str))
	fmt.Println("data", len(data), ";", data, ";", []byte(data))
	// Here I get `parsing "2": invalid argument`
	// when passing "0 2" to websocket connection
	minutes, ok := strconv.Atoui(data)
	if ok != nil {
		panic(ok.String())
	}
	_ = minutes
}

Output:

parsing "": invalid argument
tmp: 0
str: 4 ; 0 2 ; [48 32 50 0]
data 2 ; 2 ; [50 0]
panic: parsing "2": invalid argument

runtime.panic+0xac /home/peter/gor/src/pkg/runtime/proc.c:1254
	runtime.panic(0x4492c0, 0xf840002460)
main.main+0x603 /home/peter/gopath/src/so/temp.go:24
	main.main()
runtime.mainstart+0xf /home/peter/gor/src/pkg/runtime/amd64/asm.s:78
	runtime.mainstart()
runtime.goexit /home/peter/gor/src/pkg/runtime/proc.c:246
	runtime.goexit()
----- goroutine created by -----
_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,

buf := make([]byte, 512)
buf = buf[:cap(buf)]
n, err := ws.Read(buf)
if err != nil {
    panic(err.String())
}
fmt.Println(len(buf), n)
buf = buf[:n]
fmt.Println(len(buf), n)

Also, try using this code to set tmp,

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

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:

确定