在分配时解压缩Golang切片?

时间:2013-11-07 09:27:32

标签: go

Golang中是否有一种优雅的方式可以从Python中的数组中执行多项赋值?这是我正在尝试做的Python示例(拆分字符串然后将结果数组分配给两个变量)。

python:
>>> a, b = "foo;bar".split(";")

我目前的解决方案是:

x := strings.Split("foo;bar", ";")
a, b := x[0], x[1]

我可以看到这在一些结构中变得混乱。我目前面临的一个实际例子是书签文件解析并分配给地图:

bookmark := make(map[string]string)
x := strings.Split("foo\thttps://bar", "\t")
name, link := x[0], x[1]
bookmark[name] = link

现在我有一个无用的变量“x”。我想做点什么:

bookmark := make(map[string]string)
name, line := strings.Split("foo\thttps://bar", "\t")
bookmark[name] = link

但那是无效的。

3 个答案:

答案 0 :(得分:37)

正如Sergio Tulentsev所提到的,不支持使用Python完成的一般打包/解包。我认为去那里的方法是使用多个返回值来定义自己的小型ad-hoc函数:

func splitLink(s, sep string) (string, string) {
    x := strings.Split(s, sep)
    return x[0], x[1]
}

然后你可以写:

name, link := splitLink("foo\thttps://bar", "\t")

但是,这显然只有在至少有两个子串被拆分时才会起作用,并且如果超过两个则会默默地忽略。如果这是你经常使用的东西,它可能会使你的代码更具可读性。

<强> - 编辑 -

解压缩数组的另一种方法是通过可变参数指针参数:

func unpack(s []string, vars... *string) {
    for i, str := range s {
        *vars[i] = str
    }
}

让你写一下:

var name, link string
unpack(strings.Split("foo\thttps://bar", "\t"), &name, &link)
bookmarks[name] = link

这适用于任何数组大小,但可读性较差,您必须明确声明变量。

答案 1 :(得分:10)

如果您的函数仅用于在第一次出现分隔符时拆分字符串,则可以随时创建自己的函数:

package main

import (
    "fmt"
    "strings"
)

func Split(s, sep string) (string, string) {
    // Empty string should just return empty
    if len(s) == 0 {
        return s, s
    }   

    slice := strings.SplitN(s, sep, 2)

    // Incase no separator was present
    if len(slice) == 1 {
        return slice[0], ""
    }

    return slice[0], slice[1]
}

func main() {
    a, b := Split("foo;bar;foo", ";")
    fmt.Println(a, b)
}

输出:

  

foo bar; foo

Playground

答案 2 :(得分:0)

您还可以使用匿名函数:

a, b := func() (string, string) {
    x := strings.Split("foo;bar", ";")
    return x[0], x[1]
}()

注意:请不要忘记右括号()末尾的},否则会出现错误:

assignment mismatch: 2 variable but 1 values

这是因为没有()的情况下将返回一个函数(1个值)而不是预期的字符串(2个值)。