Передача указателя на строку, когда функция принимает интерфейс? - PullRequest
0 голосов
/ 25 августа 2018

Я передаю указатель на строку в метод, который принимает интерфейс (у меня есть несколько версий метода с разными получателями, поэтому я пытаюсь работать с пустыми интерфейсами, чтобы я не оказался в конечном итогес кучей безумия. По сути, я хочу заполнить строку первым значением в срезе. Я могу видеть, как значение заполняется внутри функции, но затем по какой-то причине, в моем приложении, которое вызывает его,значение не меняется. Я подозреваю, что это какая-то проблема с арифметикой указателей, но я действительно могу использовать некоторую помощь!

У меня есть следующий интерфейс:

type HeadInterface interface{
    Head(interface{})
}

И затем у меня естьследующие функции:

func Head(slice HeadInterface, result interface{}){
    slice.Head(result)
}

func (slice StringSlice) Head(result interface{}){
    result = reflect.ValueOf(slice[0])
    fmt.Println(result)
}

и ... вот мой вызов функции из приложения, которое вызывает метод ...

func main(){
    test := x.StringSlice{"Phil", "Jessica", "Andrea"}

    // empty result string for population within the function
    var result string = ""

    // Calling the function (it is a call to 'x.Head' because I lazily just called th import 'x')
    x.Head(test, &result)

    // I would have thought I would have gotten "Phil" here, but instead, it is still empty, despite the Println in the function, calling it "phil.
    fmt.Println(result)
}

* ПРИМЕЧАНИЕ: я знаю, что получениепервый элемент не должен быть таким сложным и может быть slice [0] как прямое утверждение, но это скорее упражнение в повторно используемом коде, а также в попыткечтобы получить представление об указателях, поэтому, пожалуйста, не указывайте на это решение - я бы получил гораздо больше пользы от решения моей настоящей проблемы здесь * :)

1 Ответ

0 голосов
/ 25 августа 2018

Как вы сказали в своем ПРИМЕЧАНИЕ, я почти уверен, что это не должно быть таким сложным, но чтобы заставить его работать в вашем контексте:

package main

import (
    "fmt"
    "reflect"
)

type HeadInterface interface {
    Head(interface{})
}

func Head(slice HeadInterface, result interface{}) {
    slice.Head(result)
}

type StringSlice []string

func (slice StringSlice) Head(result interface{}) {
    switch result := result.(type) {
    case *string:
        *result = reflect.ValueOf(slice[0]).String()
        fmt.Println("inside Head:", *result)
    default:
        panic("can't handle this type!")
    }

}

func main() {
    test := StringSlice{"Phil", "Jessica", "Andrea"}

    // empty result string for population within the function
    var result string = ""

    // Calling the function (it is a call to 'x.Head' because I lazily just called th import 'x')
    Head(test, &result)

    // I would have thought I would have gotten "Phil" here, but instead, it is still empty, despite the Println in the function, calling it "phil.
    fmt.Println("outside:", result)
}

Сложная часть работы с интерфейсом{} заключается в том, что трудно быть точным в отношении поведения типа, учитывая, что интерфейс {} является наиболее неопределенным типом.Чтобы изменить переменную, которую вы передаете в качестве указателя на функцию, вы должны использовать звездочку (разыменование) (например, * результат) для переменной, чтобы изменить значение, на которое она указывает, а не сам указатель.Но чтобы использовать звездочку, вы должны знать, что это фактически указатель (что-то, что интерфейс {} не говорит вам), поэтому я использовал переключатель типа, чтобы убедиться, что это указатель на строку.

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