Unpack slices on assignment?

后端 未结 3 624
误落风尘
误落风尘 2020-12-25 09:36

Is there an elegant way in Go to do multiple assignments from arrays like in Python? Here is a Python example of what I\'m trying to do (split a string and then assign the r

相关标签:
3条回答
  • 2020-12-25 10:14

    If your function is meant to split a string only by the first occurrence of the separator, you can always make your own function:

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

    Output:

    foo bar;foo

    Playground

    0 讨论(0)
  • 2020-12-25 10:24

    You could also use anonymous functions:

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

    Note: don't forget the () on the end of the closing bracket } otherwise you will get the error:

    assignment mismatch: 2 variable but 1 values

    This is because without the () a function (1 value) is returned not the expected strings (2 values).

    0 讨论(0)
  • 2020-12-25 10:36

    As Sergio Tulentsev mentioned, general packing/unpacking as is done in Python is not supported. I think the way to go there is to define your own small ad-hoc function using multiple return values:

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

    And you can then write:

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

    But this will obviously work only when at least two substrings are being split, and silently ignore if more than two were. If this is something you use a lot, it might make your code more readable though.

    --EDIT--

    Another way to unpack an array is via variadic pointer arguments:

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

    Which let you write:

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

    This will work for any array size, but it is arguably less readable, and you have to declare your variables explicitly.

    0 讨论(0)
提交回复
热议问题