21

Sorry for the basic question. I'd like to pass a slice as arguments to fmt.Sprintf. Something like this:

values := []string{"foo", "bar", "baz"}
result := fmt.Sprintf("%s%s%s", values...)

And the result would be foobarbaz, but this obviously doesn't work.

(the string I want to format is more complicated than that, so a simple concatenation won't do it :)

So the question is: if I have am array, how can I pass it as separated arguments to fmt.Sprintf? Or: can I call a function passing an list of arguments in Go?

5 Answers 5

29

As you found out on IRC, this will work:

values := []interface{}{"foo", "bar", "baz"}
result := fmt.Sprintf("%s%s%s", values...)

Your original code doesn't work because fmt.Sprintf accepts a []interface{} and []string can't be converted to that type, implicitly or explicitly.

Sign up to request clarification or add additional context in comments.

5 Comments

This is less practical in some use cases. For example, I'm trying to match an interface which takes a ...string argument, so I can't change the type to []interface{} without explicitly allocating a new slice and copying all of the elements over.
Yes, that's true and unfortunate. In that case you have to figure out whether it's worth the allocate-and-copy or find another solution.
@EvanShaw what is the purpose of having values...?
values... is equivalent to fmt.Sprintf("%s%s%s", "foo", "bar", "baz"), while values is equivalent to fmt.Sprintf("%s%s%s", []interface{}{"foo", "bar", "baz"}). The latter is probably not what you want and will produce an error message at runtime.
what if i dont know how many values there is, you gave convenient example with 3 but it feels like the question is more generic than that...
4

If the format is strictly like what you asked, then the accepted answer is indeed the way to go.

Fyi, if it is for logging purposes where you simply want to print them, then another way is by using %v

values := []string{"foo", "bar", "baz"}
result := fmt.Sprintf("%v", values)
fmt.Println(result)

result:

[foo bar baz]

Go playground: https://go.dev/play/p/_fZrT9mMmdb

Comments

2

if not use array, use args ...any

package main

import "fmt"

func main() {
    format := "%d,%d: %s"

    check(format, 4, 5, "hello")
}

func check(format string, args ...any) {

    fmt.Printf(format, args...)
}

Comments

0

If it's as simple as joining array values, using Join function can be an option:

func main() {
    values := []string{"one", "two", "three"}
    fmt.Println(strings.Join(values, ""))
}

If it's more complicated, then you can have a function like this:

func PrintValues(values []string) string {
    result := ""
    for _, val := range values {
        result = fmt.Sprintf("%s%s", result, val)
    }

    return result
}

func main() {
    values := []string{"one", "two", "three"}
    fmt.Println(PrintValues(values))
}

You can change what it does in for loop

If the array is big and you have many strings to concatenate, you can use a buffer for better performance:

func PrintValues(values []string) string {
    var buffer bytes.Buffer
    for _, val := range values {
        buffer.WriteString(val)
    }

    return buffer.String()
}

Comments

-1

I think the issue with doing this is that the Sprintf won't work with unbounded length slices, so it's not practical. The number of format parameters must match the number of formatting directives. You will either have to extract them into local variables or write something to iterate the slice and concatenate the strings together. I'd go for the latter.

3 Comments

I got an answer on IRC: it will with values := []interface{}{"foo", "bar", "baz"}.
I'm afraid on this one you are not even wrong. What is an "unbounded length slices"? There is no such thing in Go, all slices have a len() and a cap().
i.e. the length is not known at compile time. I should be more clear.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.