바이트 배열에 문자열을 할당하는 방법


375

바이트 배열에 문자열을 할당하고 싶습니다.

var arr [20]byte
str := "abc"
for k, v := range []byte(str) {
  arr[k] = byte(v)
}

다른 방법이 있습니까?


11
길이가 길이 str보다 길면 arr"색인이 범위를 벗어남"오류가 발생합니다.
peterSO

답변:


543

안전하고 간단합니다.

[]byte("Here is a string....")

14
이동 최고의 코딩 사례가 바이트의 조각 사용 []byte하고 있지 바이트의 집합 배열 [20]byte바이트 문자열을 변환 ... 할 일이 나를 믿지? 이 글타래
openwonk

9
OP는 슬라이스가 아닌 배열에 대해 물었습니다. 경우에 따라 슬라이스의 크기를 제한하고 대신 배열을 사용해야합니다. 아래의 대답은 배열을 오버플로하지 않도록 추가 문자를 자릅니다.
DavidG

3
이것이 조금 이상해 보인다고 생각하는 사람들을 위해 : 이것은 Go의 형식 변환입니다 : golang.org/ref/spec#Conversions
Cnly

여러 문자열을 추가하고 연결하는 방법은 무엇입니까? 예를 들어 []byte("one", "two")?
rakim

불행히도, @rakim, 하나의 문자열 만 전달할 수 있습니다 ... 먼저 문자열을 연결하거나 여러 바이트 조각을 결합해야합니다 (이 질문의 범위를 벗어남).
openwonk

149

문자열에서 바이트 슬라이스로 변환하는 경우 string -> []byte:

[]byte(str)

배열을 슬라이스로 변환하려면 [20]byte -> []byte다음을 수행하십시오.

arr[:]

문자열을 배열에 복사하려면 string -> [20]byte:

copy(arr[:], str)

위와 동일하지만 먼저 문자열을 슬라이스로 명시 적으로 변환합니다.

copy(arr[:], []byte(str))

  • 내장 copy기능 은 슬라이스 에서 슬라이스 로만 복사 합니다 .
  • 배열은 "기본 데이터"이고 슬라이스는 "기본 데이터의 뷰포트"입니다.
  • 를 사용 [:]하면 배열을 슬라이스로 사용할 수 있습니다.
  • 문자열을 복사 할 수있는 슬라이스로 인정하지 않습니다 ,하지만 복사 할 수있는 슬라이스 자격 에서 (문자열은 불변).
  • 문자열이 너무 길면, copy맞는 문자열 부분 만 복사합니다.

이 코드는 :

var arr [20]byte
copy(arr[:], "abc")
fmt.Printf("array: %v (%T)\n", arr, arr)

... 다음 출력을 제공합니다.

array: [97 98 99 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] ([20]uint8)

Go Playground 에서도 이용할 수있었습니다


단일 문자를 변환하기위한 예를 추가 할 수 있습니다. 나는 이것이 b[i] = []byte("A")[0]작동 하는 것으로 추론 했지만 b[i] = 'A'훨씬 더 깨끗해졌습니다.
Alex Jansen '12

1
멀티 바이트 룬에서는 작동하지 않습니다 :b[1] = '本'
Alexander

110

예를 들어

package main

import "fmt"

func main() {
    s := "abc"
    var a [20]byte
    copy(a[:], s)
    fmt.Println("s:", []byte(s), "a:", a)
}

산출:

s: [97 98 99] a: [97 98 99 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]

3
이것은 실제로 원래의 질문을 다루는 유일한 대답입니다.
Jack O'Connor

실제로 문자열에 필요한 것이 아닌 20 바이트를 할당하는 이유는 무엇입니까? 문자열이 20보다 작 으면 비트가 비효율적이지 않습니까? 또한 20을 초과하면 오류가 발생하기 쉽습니다.
Sir

1
@ 선생님 : 우리는 20 바이트를 할당하지 않습니다. 우리는 길이가 3 바이트를 복사한다 s.`복사 함수는 바보가 아니다. 슬라이스 추가 및 복사 : "복사 된 요소 수는 len (src) 및 len (dst)의 최소값입니다."
peterSO

42

케이크 조각 :

arr := []byte("That's all folks!!")

8
이것은 질문에 대답하지 않는 것 같습니다. OP는 문자열보다 더 긴 기존 배열에 문자열의 바이트를 쓰려고했습니다.
잭 오코너

2
[]byte배열보다 슬라이스를 사용하는 것이 좋습니다 [20]byte. 모범 사례를 바탕으로 답변이 정확합니다. 스펙이나 코드가 배열을 필요로하는 경우, copy대신에 사용 하십시오 (이 스레드의 다른 곳의 예 참조).
openwonk

25

더 낫다고 생각합니다 ..

package main

import "fmt"

func main() {
    str := "abc"
    mySlice := []byte(str)
    fmt.Printf("%v -> '%s'",mySlice,mySlice )
}

여기를 확인하십시오 : http://play.golang.org/p/vpnAWHZZk7


3
더 좋지 않습니다. 잘못 됐어 질문이 요구하는 것을하지 않습니다.
peterSO

10

문자열을 바이트 슬라이스로 변환

[] 문자열을 [] 바이트 유형으로 변환하는 빠른 방법이 필요합니다. 텍스트 데이터를 랜덤 액세스 파일 또는 입력 데이터가 [] 바이트 유형이어야하는 다른 유형의 데이터 조작에 저장하는 등의 상황에서 사용합니다.

package main

func main() {

    var s string

    //...

    b := []byte(s)

    //...
}

바이트 슬라이스를 데이터 매개 변수로 허용하는 ioutil.WriteFile을 사용할 때 유용합니다.

WriteFile func(filename string, data []byte, perm os.FileMode) error

또 다른 예

package main

import (
    "fmt"
    "strings"
)

func main() {

    stringSlice := []string{"hello", "world"}

    stringByte := strings.Join(stringSlice, " ")

    // Byte array value
    fmt.Println([]byte(stringByte))

    // Corresponding string value
    fmt.Println(string([]byte(stringByte)))
}

산출:

[104 101108108111 32119111114108100] 안녕하세요 세계

링크 놀이터를 확인하십시오


0

이를 위해 배열 특정 메소드를 작성했습니다. 각 int 유형에 대한 특정 메소드가 있는 인코딩 / 이진 패키지와 매우 유사합니다 . 예를 들면 binary.BigEndian.PutUint16([]byte, uint16).

func byte16PutString(s string) [16]byte {
    var a [16]byte
    if len(s) > 16 {
        copy(a[:], s)
    } else {
        copy(a[16-len(s):], s)
    }
    return a
}

var b [16]byte
b = byte16PutString("abc")
fmt.Printf("%v\n", b)

산출:

[0 0 0 0 0 0 0 0 0 0 0 0 0 97 98 99]

오른쪽이 아닌 왼쪽에 어떻게 패딩을 원했는지 확인하십시오.

http://play.golang.org/p/7tNumnJaiN


3
답변을 아래로 투표하는 경우 솔루션이 최적이 아닌 이유 또는 OP의 질문과 관련이없는 방법에 대한 의견을 남겨주십시오.
DavidG

3
다운 보트는 byte16PutString내장 copy함수를 일종의 다시 구현 하기 때문에 기존 배열을 사용하는 대신 새 배열 만들기 만 지원 하기 때문이라고 생각합니다 . copy특별한 컴파일러 지원을 가지고 있으므로 다양한 유형의 인수를 처리 할 수 ​​있으며 아마도 실제로 고성능 구현을 포함하고있을 것입니다. 또한 OP의 질문은 새로운 배열을 할당하는 대신 기존 배열에 문자열을 작성하는 것에 대한 질문을했지만 대부분의 다른 답변도 무시하는 것 같습니다.
Jack O'Connor

@ JackO'Connor에게 감사드립니다. 저는 학습을 위해 여기에 왔으며 단순한 downvote뿐만 아니라 건설적인 피드백에 감사드립니다.
DavidG

answer모든 투표 가 올바른지 모르겠다. 모든 신체가 다른 사람들을 배우고 격려하기 위해 여기에있다
muthukumar helius

-1

위에서 언급 한 방법 외에도 다음과 같은 트릭을 수행 할 수 있습니다

s := "hello"
b := *(*[]byte)(unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(&s))))

플레이 : http://play.golang.org/p/xASsiSpQmC

이것을 사용해서는 안됩니다 :-)


1
이건 미친 짓이야 나는 당신의 응답의 끝에 "하지만 당신은하지 않아야"추가 가치가 있다고 생각합니다. 실제로 질문에 대답하지 않는 사실 (OP가 슬라이스가 아닌 바이트 배열에 대해 이야기 함) 외에도 []byte"전환"을 사용하여 적절한 객체 를 얻지 못하는 것 같습니다. 수정하려고하면 잘못 실패합니다 p. play.golang.org/p/WHGl756ucj . 귀하의 경우, 왜 b := []byte(s)방법 보다 이중 안전하지 않은 것을 선호하는지 확실하지 않습니다 .
tomasz

1
@tomasz 나는 다른 방법을 보여주는 문자열 <-> [] 바이트를 선호하지 않습니다 :-) 그리고 그렇습니다. 그렇습니다. 질문을 오해했습니다.
Brandon Gao

이 작업을 수행하면 결과 cap()의 크기가 임의의 크기이므로 알 수없는 메모리를 읽습니다. 이것이 맞기 위해서는 전체 reflect.SliceHeader크기 를 할당 하고 수동으로을 설정 해야한다고 생각 합니다 cap. 다음과 같은 것 : play.golang.org/p/fBK4dZM-qD
Lye Fish

그리고 내가 그조차 확실하지 않다 .------------- ^ - 어쩌면 이것이 더 : play.golang.org/p/NJUxb20FTG
잿물 물고기

-1

배열은 값입니다 ... 슬라이스는 포인터와 비슷합니다. 즉이 [n]type와 호환되지 않습니다 []type그들이 근본적으로 다른 두 가지이기 때문에. 백업 저장소와 같은 arr[:]슬라이스를 반환 하여 배열을 가리키는 슬라이스를 얻을 수 있습니다 arr.

[]byte를 들어 슬라이스를 변환하는 한 가지 방법 [20]byte은 (값이 필요 하지 않으므로 ) [20]byte사용하여 수행 할 수 있는 것을 실제로 할당 한 다음 데이터를 복사하는 것입니다.var [20]bytemake

buf := make([]byte, 10)
var arr [10]byte
copy(arr[:], buf)

본질적으로 다른 많은 답변이 잘못 []type되면 배열이 아닙니다.

[n]T[]T완전히 다른 것입니다!

리플렉션을 사용할 때는 []TArray가 아닌 Slice와 [n]TArray가됩니다.

또한 사용할 수는 없지만 사용할 map[[]byte]T수 있습니다 map[[n]byte]T.

예를 들어 많은 함수가 작동하는 []byte반면 일부 함수는 [n]byte(대부분 해시 함수 crypto/*)를 반환 하기 때문에 때로는 성 가실 수 있습니다 . 예를 들어 sha256 해시는 초보자가 파일에 쓰려고 할 때 [32]byte그렇지 않습니다 []byte.

sum := sha256.Sum256(data)
w.Write(sum)

그들은 오류가 발생합니다. 올바른 방법은 사용하는 것입니다

w.Write(sum[:])

그러나 원하는 것이 무엇입니까? 바이트 단위로 문자열에 액세스합니까? 다음 string[]byte사용하여 a 를 쉽게 변환 할 수 있습니다 .

bytes := []byte(str)

그러나 이것은 배열이 아니며 슬라이스입니다. 또한 byte! = rune입니다. "문자"를 조작하려면 rune... not 을 사용해야 byte합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.