Перейти строка в int Atoi неверный аргумент - PullRequest
0 голосов
/ 11 февраля 2012

Я пытаюсь проанализировать строку из соединения WebSockets на языке Go. Я реализую обе стороны соединения, поэтому спецификация формата данных зависит только от меня.

Поскольку это простое приложение (обычно для учебных целей), я придумал ActionId Data, где ActionId - это uint8. BackendHandler - это обработчик для каждого запроса в WebSocket Connection.

Информация о платформе

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

код:

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")
  }
}

Весь вывод: (обратите внимание на 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 (в зависимости от окончания файла он может выглядеть по-разному в других ОС). Этот код можно исправить, добавив конечный индекс для reslice, следующим образом:

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

1 Ответ

1 голос
/ 11 февраля 2012

Вы не предоставили небольшую скомпилируемую и работающую программу для иллюстрации вашей проблемы.Также вы не предоставили полных и значимых диагностических сообщений для печати. ​​

Я думаю, у вас есть строка с нулевым символом в конце в стиле C.Например, для упрощения вашего кода,

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
}

Вывод:

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], что эквивалентно пустому string "".

Я подозреваю, что ваша проблема в том, что вы игнорируетеn возвращаемое значение от ws.Read.Например (я думаю, включая диагностические сообщения),

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())
}
...