Подтвердить что ты не робот

Идиоматический способ выполнения преобразования/утверждения типа для нескольких возвращаемых значений в Go

Каков идиоматический способ применения нескольких возвращаемых значений в Go?

Можете ли вы сделать это в одной строке или вам нужно использовать временные переменные, например, я сделал в моем примере ниже?

package main

import "fmt"

func oneRet() interface{} {
    return "Hello"
}

func twoRet() (interface{}, error) {
    return "Hejsan", nil
}

func main() {
    // With one return value, you can simply do this
    str1 := oneRet().(string)
    fmt.Println("String 1: " + str1)

    // It is not as easy with two return values
    //str2, err := twoRet().(string) // Not possible
    // Do I really have to use a temp variable instead?
    temp, err := twoRet()
    str2 := temp.(string)
    fmt.Println("String 2: " + str2 )


    if err != nil {
        panic("unreachable")
    }   
}

Кстати, называется ли это casting, когда дело доходит до интерфейсов?

i := interface.(int)
4b9b3361

Ответ 1

Вы не можете сделать это в одной строке. Ваш временный переменный подход - это путь.

Кстати, это называется литье, когда дело доходит до интерфейсов?

На самом деле это называется утверждение типа. Преобразование типа cast отличается:

var a int
var b int64

a = 5
b = int64(a)

Ответ 2

func silly() (interface{}, error) {
    return "silly", nil
}

v, err := silly()
if err != nil {
    // handle error
}

s, ok := v.(string)
if !ok {
    // the assertion failed.
}

но более вероятно, что вы действительно хотите использовать переключатель типа, например-a-this:

switch t := v.(type) {
case string:
    // t is a string
case int :
    // t is an int
default:
    // t is some other type that we didn't name.
}

Go действительно больше о правильности, чем о терпении.

Ответ 3

template.Most - это стандартный библиотечный подход для возврата только первого возвращаемого значения в один оператор. Это можно сделать аналогично для вашего случая:

func must(v interface{}, err error) interface{} {
    if err != nil {
        panic(err)
    }
    return v
}

// Usage:
str2 := must(twoRet()).(string)

Используя must, вы в основном говорите, что никогда не должно быть ошибки, и если есть, то программа не может (или, по крайней мере, не должна) продолжать работать, и будет паниковать вместо этого.

Ответ 4

Или просто в одном, если:

if v, ok := value.(migrater); ok {
    v.migrate()
}

Go позаботится о литье внутри предложения if и даст вам доступ к свойствам литого типа.