>백엔드 개발 >Golang >Go에서 인터페이스 값의 전체 복사본을 얻는 방법은 무엇입니까?

Go에서 인터페이스 값의 전체 복사본을 얻는 방법은 무엇입니까?

Mary-Kate Olsen
Mary-Kate Olsen원래의
2024-12-07 20:57:12739검색

How to Achieve a Deep Copy of Interface Values in Go?

Go에서 인터페이스 값의 전체 복사본

Go에서 인터페이스 값을 직접 복사하면 얕은 복사본이 생성됩니다. 값은 원본에도 영향을 미칩니다. 이는 인터페이스가 기본 구체적인 유형에 대한 참조를 보유하기 때문입니다.

이름 변경 원인

제공된 코드의 문제를 이해하기 위해 인터페이스 값이 작동하는 방식을 분석해 보겠습니다. . 사용자 인터페이스는 계약을 나타내며 관리자와 사용자 모두 이 계약을 구현합니다. user1을 user2에 할당할 때 기본적으로 동일한 관리 인스턴스에 대한 참조를 생성합니다. user2의 Name() 메서드를 수정하면 공유 관리 인스턴스가 직접 수정되고, 결과적으로 user1의 이름도 변경됩니다.

Reflection을 사용한 솔루션

전체 복사를 수행하려면 다음이 필요합니다. 기본 구체적인 유형의 새 인스턴스를 만들고 이를 새 사용자 인터페이스 값으로 래핑합니다. 이를 수행하는 한 가지 방법은 리플렉션을 사용하는 것입니다. Reflect.ValueOf() 및 Reflect.Elem() 함수를 사용하여 user1에 저장된 기본 값을 가져올 수 있습니다. 그런 다음, 동일한 유형의 새 인스턴스를 생성하기 위해 Reflect.New()를 사용하고 Name() 메소드를 얻기 위해 Reflect.MethodByName()을 사용할 수 있습니다. 마지막으로 새 인스턴스에서 SetName() 메서드를 호출하고 이를 새 사용자 인터페이스 값으로 래핑할 수 있습니다.

func CloneUser(user User) User {
    val := reflect.ValueOf(user)
    if val.Kind() != reflect.Ptr {
        panic("expected pointer")
    }
    elem := val.Elem()
    t := elem.Type()
    newElem := reflect.New(t).Elem()
    newElem.MethodByName("SetName").Call([]reflect.Value{reflect.ValueOf(newElem.String())})
    return newElem.Interface().(User)
}

이 함수를 사용하면 원본에 영향을 주지 않는 복사본을 만들 수 있습니다.

var user2 User = CloneUser(user1)
user2.SetName("user2")
fmt.Println(user1.Name(), user2.Name()) // Outputs: user1 user2

위 내용은 Go에서 인터페이스 값의 전체 복사본을 얻는 방법은 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.