Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unpack slices on assignment?

Tags:

go

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 resulting array into two variables).

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

My current solution is:

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

I'm can see this getting messy in some constructs. The practical example I'm currently facing is a bookmark file parsing and assigning to a map:

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

Now I have a useless variable x sitting around. I'd like to do something like:

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

but that's invalid.

like image 706
Sebastian Bartos Avatar asked Nov 07 '13 09:11

Sebastian Bartos


People also ask

What is slice assignment in Python?

Slice assignment is a little-used, beautiful Python feature to replace a slice with another sequence. Simply select the slice you want to replace on the left and the values to replace it on the right side of the equation.

How do you unpack a string in Python?

Method : Using format() + * operator + values() The * operator is used to unpack and assign. The values are extracted using values().

What is parallel assignment in Python?

One of the most common use-cases of unpacking in Python is what we can call parallel assignment. Parallel assignment allows you to assign the values in an iterable to a tuple (or list ) of variables in a single and elegant statement.


2 Answers

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.

like image 52
val Avatar answered Sep 23 '22 03:09

val


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

like image 31
ANisus Avatar answered Sep 24 '22 03:09

ANisus