반복하는 동안 값 변경
이 유형이 있다고 가정 해 봅시다.
type Attribute struct {
Key, Val string
}
type Node struct {
Attr []Attribute
}
노드 속성을 반복하여 변경하고 싶습니다.
나는 할 수 있기를 바랐습니다.
for _, attr := range n.Attr {
if attr.Key == "href" {
attr.Val = "something"
}
}
그러나 attr
포인터가 아니기 때문에 이것은 작동하지 않으며 수행해야합니다.
for i, attr := range n.Attr {
if attr.Key == "href" {
n.Attr[i].Val = "something"
}
}
더 간단하거나 빠른 방법이 있습니까? 직접 포인터를 얻을 수 range
있습니까?
분명히 반복을 위해 구조를 변경하고 싶지 않으며 더 자세한 솔루션은 솔루션이 아닙니다.
아니요, 원하는 약어는 불가능합니다.
그 이유 range
는 반복하는 슬라이스의 값 을 복사하기 때문입니다 . 범위에 대한 사양은 말합니다 :
Range expression 1st value 2nd value (if 2nd variable is present) array or slice a [n]E, *[n]E, or []E index i int a[i] E
따라서 range는 a[i]
배열 / 슬라이스의 두 번째 값으로 사용 됩니다. 즉, 값이 복사되어 원래 값을 건드리지 못하게됩니다.
이 동작은 다음 코드로 설명됩니다 .
x := make([]int, 3)
x[0], x[1], x[2] = 1, 2, 3
for i, val := range x {
println(&x[i], "vs.", &val)
}
이 코드는 범위의 값과 슬라이스의 실제 값에 대해 완전히 다른 메모리 위치를 인쇄합니다.
0xf84000f010 vs. 0x7f095ed0bf68
0xf84000f014 vs. 0x7f095ed0bf68
0xf84000f018 vs. 0x7f095ed0bf68
따라서 jnml 및 peterSO에서 이미 제안한대로 포인터 또는 색인을 사용하는 것이 유일한 방법입니다.
당신은 이것과 동등한 것을 요구하는 것 같습니다 :
package main
import "fmt"
type Attribute struct {
Key, Val string
}
type Node struct {
Attr []Attribute
}
func main() {
n := Node{
[]Attribute{
{"key", "value"},
{"href", "http://www.google.com"},
},
}
fmt.Println(n)
for i := 0; i < len(n.Attr); i++ {
attr := &n.Attr[i]
if attr.Key == "href" {
attr.Val = "something"
}
}
fmt.Println(n)
}
산출:
{[{key value} {href http://www.google.com}]}
{[{key value} {href something}]}
이렇게하면 Attribute
슬라이스 경계 검사를 희생시키면서 유형 값을 복사 할 수 있습니다 . 귀하의 예에서 유형 Attribute
은 string
64 비트 아키텍처 시스템에서 비교적 작은 두 개의 슬라이스 참조입니다. 2 * 3 * 8 = 48 바이트.
간단히 쓸 수도 있습니다.
for i := 0; i < len(n.Attr); i++ {
if n.Attr[i].Key == "href" {
n.Attr[i].Val = "something"
}
}
But, the way to get an equivalent result with a range
clause, which creates a copy but minimizes slice bounds checks, is:
for i, attr := range n.Attr {
if attr.Key == "href" {
n.Attr[i].Val = "something"
}
}
I'd adapt your last suggestion and use the index-only version of range.
for i := range n.Attr {
if n.Attr[i].Key == "href" {
n.Attr[i].Val = "something"
}
}
It seems simpler to me to refer to n.Attr[i]
explicitly in both the line that tests Key
and the line that sets Val
, rather than using attr
for one and n.Attr[i]
for the other.
For example:
package main
import "fmt"
type Attribute struct {
Key, Val string
}
type Node struct {
Attr []*Attribute
}
func main() {
n := Node{[]*Attribute{
&Attribute{"foo", ""},
&Attribute{"href", ""},
&Attribute{"bar", ""},
}}
for _, attr := range n.Attr {
if attr.Key == "href" {
attr.Val = "something"
}
}
for _, v := range n.Attr {
fmt.Printf("%#v\n", *v)
}
}
Output
main.Attribute{Key:"foo", Val:""}
main.Attribute{Key:"href", Val:"something"}
main.Attribute{Key:"bar", Val:""}
Alternative approach:
package main
import "fmt"
type Attribute struct {
Key, Val string
}
type Node struct {
Attr []Attribute
}
func main() {
n := Node{[]Attribute{
{"foo", ""},
{"href", ""},
{"bar", ""},
}}
for i := range n.Attr {
attr := &n.Attr[i]
if attr.Key == "href" {
attr.Val = "something"
}
}
for _, v := range n.Attr {
fmt.Printf("%#v\n", v)
}
}
Output:
main.Attribute{Key:"foo", Val:""}
main.Attribute{Key:"href", Val:"something"}
main.Attribute{Key:"bar", Val:""}
참고URL : https://stackoverflow.com/questions/15945030/change-values-while-iterating
'IT' 카테고리의 다른 글
브라우저에서 JWT를 어디에 저장합니까? (0) | 2020.06.27 |
---|---|
JavaScript에는 해시 코드 함수가 있습니까? (0) | 2020.06.27 |
도커 및 보안 비밀번호 (0) | 2020.06.27 |
NPM에서 devDependencies를 어떻게 업데이트합니까? (0) | 2020.06.27 |
DB 스키마 변경 사항을 추적하는 메커니즘 (0) | 2020.06.27 |