Go字符串问题

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

Go issue with strings

问题

我在Golang中遇到了一些字符串的问题。似乎它们没有传递给另一个函数。

func Sendtext(ip string, port string, text string) (err int) {
    targ := ip + ":" + port
    raddr,e := net.ResolveTCPAddr("tcp",targ)
    if e != nil {
        os.Stdout.WriteString(e.String()+"\n")
        return 1
    }
    conn,e := net.DialTCP("tcp",nil,raddr)
    if e != nil {
        os.Stdout.WriteString(e.String()+"\n")
        return 1
    }
    conn.Write([]byte(text))
    mess := make([]byte,1024)
    conn.Read(mess)
    message := string(mess)
    conn.Close()
    if message[0] == 'a' {
        return 0
    } else {
        return 1
    }
    return 0
}

func main() {
    os.Stdout.WriteString("Will send URL: ")
    url := GetURL()
    os.Stdout.WriteString(url + "\n\n")
    _, port, pass, ip := browserbridge_config.ReadPropertiesFile()
    os.Stdout.WriteString("sending this url to " + ip + ":" + port + "\n")
    message := url + "\n" + pass + "\n"
    os.Stdout.WriteString("\nsending... ")
    e := Sendtext(ip, port, message)
    if e != 0 {
        os.Stdout.WriteString("ERROR\n")
        os.Exit(e);
    }
    os.Stdout.WriteString("DONE\n")
}

func ReadConfigFile(filename string) (browsercommand string, port string, pass string, ip string) {

    // set defaults
    browsercommand = "%u"
    port = "7896"
    pass = "hallo"
    ip = "127.0.0.1"

    // open file
    file, err := os.Open(filename)
    if err != nil {
        os.Stdout.WriteString("Error opening config file. proceeding with standard config...")
        return
    }


    // Get reader and buffer
    reader := bufio.NewReader(file)

    for {
        part,_,err := reader.ReadLine()
        if err != nil {
            break
        }
        buffer := bytes.NewBuffer(make([]byte,2048))
        buffer.Write(part)
        s := strings.ToLower(buffer.String())

        if strings.Contains(s,"browsercommand=") {
            browsercommand = strings.Replace(s,"browsercommand=","",1)
        } else {
            if strings.Contains(s,"port=") {
                port = strings.Replace(s,"port=","",1)
            } else {
                if strings.Contains(s,"password=") {
                    pass = strings.Replace(s,"password=","",1)
                } else {
                    if strings.Contains(s,"ip=") {
                        ip = strings.Replace(s,"ip=","",1)
                    }
                }
            }
        }
    }

    return
}

这个程序的输出是:

Will send URL: test.de
sending this url to 192.168.2.100:7896
sending... 
dial tcp 192.168.2.1:0: connection refused
ERROR

(192.168.2.1是网关)

我尝试在Sendtext的顶部添加os.Stdout.WriteString(targ)或os.Stdout.WriteString(ip),但没有输出。

关于这个问题令人困惑的是:昨天它还能工作xD(在我将ReadConfig迁移到它自己的.go文件之前)。

我希望你能帮助我解决这个问题...

sylar


更新:

正如PeterSO所说,问题不在于字符串的传递。
我最初的猜测是,它必须是从String转换为TCPAddr,这是正确的,但似乎是字符串的问题,而不是net库的问题。
我刚刚在调用Sendtext之后添加了以下代码:

ip = "192.168.2.100"
port = "7896"

这样做有所帮助...(至少在用户需要设置自定义ip/port之前是这样的...)

我知道问题最初出现在我决定从goconf(http://code.google.com/p/goconf/)切换到自己的库时。这就是为什么我认为问题出现在ReadProperties()函数中的原因。

我还意识到strconv.Atoi(port)返回0(解析"7896":无效的参数)
当我使用实现了(不可更改的)配置的服务器和客户端,然后让客户端从配置文件中读取密码时,密码比较失败。当我在代码中设置密码(而不是从文件中读取)时,它可以工作。

我真的不知道现在该怎么办...有什么建议吗?

英文:

I'm having some trouble with strings in Golang. It seems that they don't get handed over to another function.

func Sendtext(ip string, port string, text string) (err int) {
targ := ip + ":" + port
raddr,e := net.ResolveTCPAddr("tcp",targ)
if e != nil {
os.Stdout.WriteString(e.String()+"\n")
return 1
}
conn,e := net.DialTCP("tcp",nil,raddr)
if e != nil {
os.Stdout.WriteString(e.String()+"\n")
return 1
}
conn.Write([]byte(text))
mess := make([]byte,1024)
conn.Read(mess)
message := string(mess)
conn.Close()
if message[0] == 'a' {
return 0
} else {
return 1
}
return 0
}
func main() {
os.Stdout.WriteString("Will send URL: ")
url := GetURL()
os.Stdout.WriteString(url + "\n\n")
_, port, pass, ip := browserbridge_config.ReadPropertiesFile()
os.Stdout.WriteString("sending this url to " + ip + ":" + port + "\n")
message := url + "\n" + pass + "\n"
os.Stdout.WriteString("\nsending... ")
e := Sendtext(ip, port, message)
if e != 0 {
os.Stdout.WriteString("ERROR\n")
os.Exit(e);
}
os.Stdout.WriteString("DONE\n")
}

and my config reader:

func ReadConfigFile(filename string) (browsercommand string, port string, pass string, ip string) {
// set defaults
browsercommand = "%u"
port = "7896"
pass = "hallo"
ip = "127.0.0.1"
// open file
file, err := os.Open(filename)
if err != nil {
os.Stdout.WriteString("Error opening config file. proceeding with standard config...")
return
}
// Get reader and buffer
reader := bufio.NewReader(file)
for {
part,_,err := reader.ReadLine()
if err != nil {
break
}
buffer := bytes.NewBuffer(make([]byte,2048))
buffer.Write(part)
s := strings.ToLower(buffer.String())
if strings.Contains(s,"browsercommand=") {
browsercommand = strings.Replace(s,"browsercommand=","",1)
} else {
if strings.Contains(s,"port=") {
port = strings.Replace(s,"port=","",1)
} else {
if strings.Contains(s,"password=") {
pass = strings.Replace(s,"password=","",1)
} else {
if strings.Contains(s,"ip=") {
ip = strings.Replace(s,"ip=","",1)
}
}
}
}
}
return
}

Output of this program:

Will send URL: test.de
sending this url to 192.168.2.100:7896
sending... 
dial tcp 192.168.2.1:0: connection refused
ERROR

(192.168.2.1 is gateway)

I tried to os.Stdout.WriteString(targ) or os.Stdout.WriteString(ip) just at the top of Sendtext, and got no output.

The confusing thing about it: yesterday it worked xD (before I migrated ReadConfig into its own .go file)

I hope you can help me solving this...

sylar


Update:

As PeterSO said, the problem is not the handover of the strings
My first guess, that it must be the conversion of String to TCPAddr, is true, but it seems to be a problem with the strings, not with the net library.
I just added
ip = "192.168.2.100"
port = "7896"
right after the call of Sendtext, and that helped... (at least until a user needs to set a custom ip/port...)

I know that the problem firs occured when I decided to switch from goconf (http://code.google.com/p/goconf/) to my own. This is why I think the problem is in the ReadProperties() function.

I also realized that strconv.Atoi(port) returns 0 (parsing "7896": invalid argument)
When I used the server and client with implemented (not-changable) config, and then let the client read the password from the config file, the password comparison fails. When I also set the password right in the code (without reading a file), it works.

I really don't know what to do now... Any idea?

答案1

得分: 4

Go字节包:func NewBuffer(buf []byte) *Buffer

> NewBuffer使用buf作为其初始内容创建和初始化一个新的Buffer。它旨在准备一个Buffer来读取现有数据。它也可以用于调整内部缓冲区的大小。为此,buf应该具有所需的容量,但长度为零。
>
> 在大多数情况下,new(Buffer)(或只声明一个Buffer变量)比NewBuffer更可取。特别是,将非空的buf传递给NewBuffer,然后写入Buffer将覆盖buf,而不是追加到它。

在你的ReadConfigFile函数中,你写道:

buffer := bytes.NewBuffer(make([]byte,2048))
buffer.Write(part)

make([]byte,2048)函数调用创建了一个初始的切片,长度和容量都为2048字节。buffer.Write(part)函数调用通过覆盖buffer来写入part。至少,你应该写make([]byte,0,2048)来最初给buffer切片一个长度为零和容量为2048字节。

你的ReadConfigFile函数还有其他缺陷。例如,键=值格式非常严格,只有在函数中硬编码的键才会被识别,如果没有给定配置文件,则不会返回默认值,配置文件没有关闭等。这是一个基本的配置文件读取器的实现。

package main
import (
"bufio"
"fmt"
"os"
"strings"
)
type Config map[string]string
func ReadConfig(filename string) (Config, os.Error) {
config := Config{
"browsercommand": "%u",
"port":           "7896",
"password":       "hallo",
"ip":             "127.0.0.1",
}
if len(filename) == 0 {
return config, nil
}
file, err := os.Open(filename)
if err != nil {
return nil, err
}
defer file.Close()
rdr := bufio.NewReader(file)
for {
line, err := rdr.ReadString('\n')
if eq := strings.Index(line, "="); eq >= 0 {
if key := strings.TrimSpace(line[:eq]); len(key) > 0 {
value := ""
if len(line) > eq {
value = strings.TrimSpace(line[eq+1:])
}
config[key] = value
}
}
if err == os.EOF {
break
}
if err != nil {
return nil, err
}
}
return config, nil
}
func main() {
config, err := ReadConfig(`netconfig.txt`)
if err != nil {
fmt.Println(err)
}
fmt.Println("config:", config)
ip := config["ip"]
pass := config["password"]
port := config["port"]
fmt.Println("values:", ip, port, pass)
}

输入:

[a section]
key=value
; a comment
port = 80
password  =  hello  
ip= 217.110.104.156
# another comment
url =test.de
file =

输出:

config: map[browsercommand:%u key:value port:80 ip:217.110.104.156 url:test.de
file: password:hello]
values: 217.110.104.156 80 hello
英文:

Go bytes package: func NewBuffer(buf []byte) *Buffer

> NewBuffer creates and initializes a new Buffer using buf as its
> initial contents. It is intended to prepare a Buffer to read
> existing data. It can also be used to size the internal buffer for
> writing. To do that, buf should have the desired capacity but a
> length of zero.
>
> In most cases, new(Buffer) (or just declaring a Buffer variable)
> is preferable to NewBuffer. In particular, passing a non-empty buf
> to NewBuffer and then writing to the Buffer will overwrite buf,
> not append to it.

In your ReadConfigFile function, you write:

buffer := bytes.NewBuffer(make([]byte,2048))
buffer.Write(part)

The make([]byte,2048) function call creates an initial slice for buffer with a length and capacity of 2048 bytes. The buffer.Write(part) function call writes part by overwriting buffer. At the very least, you should have written make([]byte,0,2048) to initially give the buffer slice a length of zero and capacity of 2048 bytes.

Your ReadConfigFile function has other flaws. For example, the key=value format is very rigid, only keys hardcoded into the function are recognized, if a configuration file is not given it doesn't return the defaults, the configuration file is not closed, etc. Here's a basic implementation of a configuration file reader.

package main
import (
"bufio"
"fmt"
"os"
"strings"
)
type Config map[string]string
func ReadConfig(filename string) (Config, os.Error) {
config := Config{
"browsercommand": "%u",
"port":           "7896",
"password":       "hallo",
"ip":             "127.0.0.1",
}
if len(filename) == 0 {
return config, nil
}
file, err := os.Open(filename)
if err != nil {
return nil, err
}
defer file.Close()
rdr := bufio.NewReader(file)
for {
line, err := rdr.ReadString('\n')
if eq := strings.Index(line, "="); eq >= 0 {
if key := strings.TrimSpace(line[:eq]); len(key) > 0 {
value := ""
if len(line) > eq {
value = strings.TrimSpace(line[eq+1:])
}
config[key] = value
}
}
if err == os.EOF {
break
}
if err != nil {
return nil, err
}
}
return config, nil
}
func main() {
config, err := ReadConfig(`netconfig.txt`)
if err != nil {
fmt.Println(err)
}
fmt.Println("config:", config)
ip := config["ip"]
pass := config["password"]
port := config["port"]
fmt.Println("values:", ip, port, pass)
}

Input:

[a section]
key=value
; a comment
port = 80
password  =  hello  
ip= 217.110.104.156
# another comment
url =test.de
file =

Output:

config: map[browsercommand:%u key:value port:80 ip:217.110.104.156 url:test.de
file: password:hello]
values: 217.110.104.156 80 hello

答案2

得分: 0

main函数中,在调用Sendtext函数之前,将以下语句插入为语句。

fmt.Println("main:", "\nip = |", ip, "| \nport = |", port, "| \ntext = |", message, "|")

输出应该类似于这样:

main: 
ip = | 192.168.2.100 | 
port = | 7896 | 
text = | test.de
hallo
|

Sendtext函数中,将以下语句插入为第一条语句。

fmt.Println("Sendtext:", "\nip = |", ip, "| \nport = |", port, "| \ntext = |", text, "|")

输出应该类似于这样:

Sendtext: 
ip = | 192.168.2.100 | 
port = | 7896 | 
text = | test.de
hallo
|

如预期,参数按值传递给参数。

英文:

Insert the following statement as the statement just before the call to the Sendtext function in the main function.

fmt.Println("\nmain:", "\nip = |", ip, "| \nport = |", port, "| \ntext = |", message, "|")

The output should look something like this:

main: 
ip = | 192.168.2.100 | 
port = | 7896 | 
text = | test.de
hallo
|

Insert the following statement as the first statement in the Sendtext function.

fmt.Println("\nSendtext:", "\nip = |", ip, "| \nport = |", port, "| \ntext = |", text, "|")

The output should look something like this:

Sendtext: 
ip = | 192.168.2.100 | 
port = | 7896 | 
text = | test.de
hallo
|

As expected, the arguments are passed to the parameters by value.

答案3

得分: 0

解决了。问题是将长度为2048的[]byte转换为字符串。这使得字符串长度相等,但后面有很多NIL字符。
所以在ReadConfig()的末尾运行ip = strings.Replace(ip,string(0),"",-1)解决了这个问题。

英文:

Solved it. The problem was the conversion of the 2048-long []byte to a string. This made the string to be equal long, but with a lot of NIL-chars after it.
So running a ip = strings.Replace(ip,string(0),"",-1) over all values at the end of ReadConfig() solved the problem.

huangapple
  • 本文由 发表于 2011年8月31日 04:44:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/7249576.html
匿名

发表评论

匿名网友

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

确定