*int64
필드 가있는 구조체 유형이 있습니다.
type SomeType struct {
SomeField *int64
}
내 코드의 어느 시점에서 나는 이것의 리터럴을 선언하고 싶습니다.
instance := SomeType{
SomeField: &0,
}
… 이것은 작동하지 않는 것을 제외하고
./main.go:xx: cannot use &0 (type *int) as type *int64 in field value
그래서 나는 이것을 시도
instance := SomeType{
SomeField: &int64(0),
}
…하지만 이것도 작동하지 않습니다
./main.go:xx: cannot take the address of int64(0)
어떻게해야합니까? 내가 생각 해낼 수있는 유일한 해결책은 자리 표시 자 변수를 사용하는 것입니다.
var placeholder int64
placeholder = 0
instance := SomeType{
SomeField: &placeholder,
}
참고 : 편집 : 아니요. 이렇게되어 미안합니다.&0
구문이 작동 벌금을 그것이 * INT는 대신 때 *int64
.
편집하다:
분명히 내 질문에 너무 모호한 부분이있었습니다. 내가 할 수있는 방법을 찾고 있어요 그대로 상태*int64
. 이것은 생성자 내부에서 사용하거나 리터럴 구조체 값을 지정하거나 다른 함수에 대한 인수로 사용할 수도 있습니다. 그러나 도우미 기능이나 다른 유형을 사용하는 것은 내가 찾고있는 솔루션이 아닙니다.
답변
Go 언어 사양 ( 주소 연산자 )은 숫자 상수의 주소를 허용하지 않습니다 ( 유형이 지정되지 않았거나 입력 된 상수가 아님).
피연산자는 주소 지정 이 가능 해야합니다 . 즉, 변수, 포인터 간접 지정 또는 슬라이스 인덱싱 작업 중 하나 여야합니다 . 또는 주소 지정 가능한 구조체 피연산자의 필드 선택자; 또는 주소 지정 가능한 배열의 배열 인덱싱 작업입니다. 주소 지정 요구 사항에 대한 예외로,
x
[의 표현에서&x
]는 복합 리터럴 일 수도 있습니다 (괄호 안에 있음) .
이것이 허용되지 않는 이유에 대해서는 관련 질문 : Find address of constant in go를 참조하십시오 . 유사한 질문 (비슷하게 주소를 사용할 수 없음) : Go에서 작업 결과에 대한 참조를 어떻게 저장할 수 있습니까?
옵션 ( Go Playground 에서 모두 시도 ) :
1) 함께 new()
내장 new()
함수를 사용하여 새로운 0 값을 할당 int64
하고 주소를 얻을 수 있습니다.
instance := SomeType{
SomeField: new(int64),
}
그러나 이것은 모든 유형의 0 값에 대한 포인터를 할당하고 얻는 데만 사용할 수 있습니다.
2) 도우미 변수 사용
0이 아닌 요소에 대해 가장 간단하고 권장되는 것은 주소를 가져올 수있는 도우미 변수를 사용하는 것입니다.
helper := int64(2)
instance2 := SomeType{
SomeField: &helper,
}
3) 도우미 기능 포함
참고 : 0이 아닌 값에 대한 포인터를 가져 오는 도우미 함수는 내 github.com/icza/gox
라이브러리의 gox
패키지 에서 사용할 수 있으므로 필요한 모든 프로젝트에 추가 할 필요가 없습니다.
또는 이것을 여러 번 필요로하는 경우 다음을 할당하고 반환하는 도우미 함수를 만들 수 있습니다 *int64
.
func create(x int64) *int64 {
return &x
}
그리고 그것을 사용 :
instance3 := SomeType{
SomeField: create(3),
}
실제로 아무것도 할당하지 않았으며 Go 컴파일러는 함수 인수의 주소를 반환 할 때 할당했습니다. Go 컴파일러는 이스케이프 분석을 수행하고 함수를 이스케이프 할 수있는 경우 스택 대신 힙에 지역 변수를 할당합니다. 자세한 내용 은 Go 함수에서 로컬 배열 조각을 안전하게 반환합니까?를 참조하십시오.
4) 한 줄 익명 기능 사용
instance4 := SomeType{
SomeField: func() *int64 { i := int64(4); return &i }(),
}
또는 (짧은) 대안으로 :
instance4 := SomeType{
SomeField: func(i int64) *int64 { return &i }(4),
}
5) 슬라이스 리터럴, 인덱싱 및 주소 가져 오기
*SomeField
이외의 사람 이되고 싶다면 0
주소 지정이 가능한 것이 필요합니다.
여전히 그렇게 할 수 있지만 그것은 추합니다.
instance5 := SomeType{
SomeField: &[]int64{5}[0],
}
fmt.Println(*instance2.SomeField) // Prints 5
여기서 일어나는 일은 []int64
하나의 요소 ( 5
)를 갖는 리터럴 로 슬라이스가 생성된다는 것 입니다. 그리고 색인화 (0 번째 요소)되고 0 번째 요소의 주소가 사용됩니다. 백그라운드에서의 배열 [1]int64
도 할당되고 슬라이스의 지원 배열로 사용됩니다. 여기에는 많은 상용구가 있습니다.
6) 도우미 구조체 리터럴 사용
주소 지정 요구 사항에 대한 예외를 살펴 보겠습니다.
주소 지정 요구 사항에 대한 예외로,
x
[의 표현에서&x
]는 복합 리터럴 일 수도 있습니다 (괄호 안에 있음) .
이것은 합성 리터럴 (예 : 구조체 리터럴)의 주소를 취하는 것이 괜찮다는 것을 의미합니다. 그렇게하면 구조체 값이 할당되고 포인터가 획득됩니다. 그러나 그렇다면 “주소 지정 가능한 구조체 피연산자의 필드 선택자”라는 또 다른 요구 사항을 사용할 수 있습니다 . 따라서 구조체 리터럴에 유형의 필드가 포함되어 있으면 해당 필드의 int64
주소를 가져올 수도 있습니다!
이 옵션이 실제로 작동하는지 살펴 보겠습니다. 이 래퍼 구조체 유형을 사용합니다.
type intwrapper struct {
x int64
}
이제 다음을 수행 할 수 있습니다.
instance6 := SomeType{
SomeField: &(&intwrapper{6}).x,
}
이
&(&intwrapper{6}).x
다음을 의미합니다.
& ( (&intwrapper{6}).x )
그러나 주소 연산자 &
가 선택기 표현식 의 결과에 적용 되므로 “외부”괄호를 생략 할 수 있습니다 .
또한 백그라운드에서 다음이 발생합니다 (유효한 구문이기도합니다).
&(*(&intwrapper{6})).x
7) 도우미 익명 구조체 리터럴 사용
원칙은 사례 # 6과 동일하지만 익명 구조체 리터럴을 사용할 수도 있으므로 도우미 / 래퍼 구조체 유형 정의가 필요하지 않습니다.
instance7 := SomeType{
SomeField: &(&struct{ x int64 }{7}).x,
}
답변
문제를 해결하기 위해 int64 변수의 주소를 반환하는 함수를 사용하십시오.
아래 코드에서는
f
정수를 받아들이고 정수의 주소를 보유하는 포인터 값을 반환하는 함수 를 사용합니다 . 이 방법을 사용하면 위의 문제를 쉽게 해결할 수 있습니다.
type myStr struct {
url *int64
}
func main() {
f := func(s int64) *int64 {
return &s
}
myStr{
url: f(12345),
}
}