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

Значения указателя копирования * a = * b в golang

type T struct {
    Id int
    Name string
}

func Copy(a *T, b *T) error {
    b.Id=5
    b.Name="gert"
    a = b
    return nil
}

a по-прежнему пуст, я должен сделать это так:

func Copy(a *T, b *T) error {
    b.Id = 5
    b.Name = "gert"
    a.Id = b.Id
    a.Name = b.Name
    return nil
}

теперь a совпадает с b

Почему и как я могу скопировать *b в *a напрямую?

4b9b3361

Ответ 1

Ваш первый пример почти прав. Вы передаете указатели на два объекта. Вы помещаете эти указатели в переменные A и B. Но A и B являются локальными переменными, поэтому, когда вы говорите a=b, вы просто говорите: "Забудьте, что было в (локально)". Остальная часть программы по-прежнему имеет указатели на эти два оригинальных объекта.

Если вы хотите скопировать структуру данных в B в структуру данных в A, сделайте это вместо этого:

*a = *b;

Ответ 2

В go аргументы передаются по значению.

и * T - указатель на T. Подумайте об этом как о int, который сообщает вам, где это T. Итак, "a" указывает на один экземпляр T и b указывает на другой.

в вашей функции копирования, вы говорите, чтобы указать точку b "T" (если это имело смысл). Вы хотели сказать, что T должен быть таким же, как b T

Вы делаете это путем разыменования указателей.

поэтому вместо a = b (измените мою локальную переменную "a", чтобы указать на то, что указывает "b" ) вы используете * a = * b (измените значение T равным b T)

Надеюсь, это имело смысл, вот пример вашего приложения, измененный для "правильной работы". Обратите внимание: ваша функция копирования не нужна в этом, она там для иллюстрации. Пример воспроизведения

import "fmt"

type T struct {
    Id   int
    Name string
}

func Copy(a *T, b *T) error {
    b.Id = 5
    b.Name = "gert"
    a = b
    return nil
}
func CopyThatActuallyCopies(a *T, b *T) error {
    b.Id = 5
    b.Name = "gert"
    *a = *b
    return nil
}

func main() {
    var a = &T{1, "one"}
    var b = &T{2, "two"}

    fmt.Println(a, b)
    Copy(a, b)
    fmt.Println(a, b)
    CopyThatActuallyCopies(a, b)
    fmt.Println(a, b)
}

Ответ 3

Общее решение для разработчиков инфраструктуры:

func CloneValue(source interface{}, destin interface{}) {
    x := reflect.ValueOf(source)
    if x.Kind() == reflect.Ptr {
        starX := x.Elem()
        y := reflect.New(starX.Type())
        starY := y.Elem()
        starY.Set(starX)
        reflect.ValueOf(destin).Elem().Set(y.Elem())
    } else {
        destin = x.Interface()
    }
}

Итак:

CloneValue(old, new)
см. этот код в play.golang.org

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

Ответ 4

Это неверно. Это не работает.

func (r *Request) WithContext(ctx context.Context) *Request {
  if ctx == nil {
    panic("nil context")
  }
  r2 := new(Request)
  *r2 = *r
  r2.ctx = ctx
  return r2
}