вернуть часть пустого интерфейса из функции - PullRequest
0 голосов
/ 11 июня 2018

Может кто-нибудь объяснить, почему это не работает, и как мы можем вернуть фрагменты интерфейсов, [] interface {}, из функций, как показано в примере?

import (
    "fmt"
)

func main() {
    var test []string
    Test(&test)
    fmt.Println(test)
}

func Test(t interface{}) {
    a := []interface{}{"first", "second"}
    fmt.Println(a)
    t = a
}

Пример выполнения кода может бытьнайдено здесь: https://play.golang.org/p/vcEGHSdWrjv

Кстати, это func Я пытаюсь извлечь данные из: https://godoc.org/github.com/mongodb/mongo-go-driver/mongo#Collection.Distinct

Примечание: тип, который мы ожидаем, не всегда имеет тип []string, я просто использую строку в качестве примера.

Спасибо!

Ответы [ 2 ]

0 голосов
/ 11 июня 2018

Поскольку строка [] и интерфейс [] {} являются разными типами, вы не можете назначить один другому.

Вы должны скопировать фрагмент, чтобы преобразовать интерфейс [] {} в фрагмент некоторыхконкретный тип.Если вы знаете, что интерфейс [] {} всегда содержит строковые значения, тогда используйте следующее:

func stringSlice() []string {
    a := []interface{}{"first", "second"} // query result
    fmt.Println(a)

    result := make([]string, len(a))
    for i := range a {
       var ok bool
       result[i], ok = a[i].(string)
       if !ok {
          // handle error with unexpected type
       }
    }
    return result
}

Если результат может иметь произвольные типы элементов, тогда используйте отражение , чтобы скопироватьломтик:

func anySlice(result interface{}) {
    a := []interface{}{"first", "second"} // query result

    slice := reflect.ValueOf(result).Elem()
    elementType := slice.Type().Elem()
    for _, v := range a {
        rv := reflect.ValueOf(v)
        if !rv.Type().AssignableTo(elementType) {
            // handle error with unexpected type
        }
        slice.Set(reflect.Append(slice, rv))
    }
}

Используйте это так:

var s []string
anySlice(&s)

пример игровой площадки

0 голосов
/ 11 июня 2018

В вашем примере вы не пытаетесь «вернуть» фрагмент, а скорее хотите изменить аргумент, чтобы он указывал на новый фрагмент строки.

То, как вы это делаете, делаетне работает причина в Go, аргументы передаются по значению.

Когда вы делаете это:

t = a

t является копией из &test васпосылают в функцию в качестве аргумента.

Таким образом, изменение t не приводит к изменению вашей переменной test.

Вам необходимо передать адрес указателя, чтобы иметь возможностьчтобы изменить то, на что указывает указатель.

Попробуйте сделать так:

func main() {
    var test *[]string
    Test(&test)
    fmt.Println(*test)
}

func Test(t interface{}) {
    a := []string{"first", "second"}
    fmt.Println(a)
    *t.(**[]string) = &a
}

Вывод:

[first second]
[first second]

Детская площадка: https://play.golang.org/p/tliMrmliykp

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...