strings
strings 패키지는 UTF-8 인코딩 문자열을 조작하는 간단한 함수를 구현합니다. 간단히 말해 문자열 조작을 위한 유틸리티 패키지입니다.
공식 문서: strings package - strings - Go Packages
TIP
Go 는 기본적으로 UTF8 문자를 지원하며, 모든 문자열 조작은 UTF8 을 기반으로 합니다.
가져오기
import (
"strings"
)아래에서는 예시를 통해 자주 사용되는 함수를 설명하겠습니다.
문자열 복제
func Clone(s string) string복제된 사본에 새 메모리를 할당하며, 빈 문자열을 전달하면 메모리를 할당하지 않고 빈 문자열을 반환합니다.
func TestClone(t *testing.T) {
ori := "hello 世界"
copys := strings.Clone(ori)
fmt.Println(ori, copys)
fmt.Println(&ori, ©s)
}=== RUN TestClone
hello 世界 hello 世界
0xc00005e5d0 0xc00005e5e0
--- PASS: TestClone (0.00s)
PASS문자열 비교
func Compare(a, b string) inta 와 b 를 사전 순으로 문자열 비교하며, a>b 이면 1 을 반환하고, a<b 이면 -1 을, a=b 이면 0 을 반환합니다.
func TestCompare(t *testing.T) {
fmt.Println(strings.Compare("abc", "abe"))
fmt.Println(strings.Compare("abcd", "abe"))
fmt.Println(strings.Compare("abijk", "abe"))
fmt.Println(strings.Compare("abe", "abe"))
}=== RUN TestCompare
-1
-1
1
0
--- PASS: TestCompare (0.00s)
PASS문자열 포함
func Contains(s, substr string) bool문자열 s 가 부분 문자열 substr 을 포함하는지 판단합니다.
func TestContains(t *testing.T) {
fmt.Println(strings.Contains("abcdefg", "a"))
fmt.Println(strings.Contains("abcdefg", "abc"))
fmt.Println(strings.Contains("abcdefg", "ba"))
}=== RUN TestContains
true
true
false
--- PASS: TestContains (0.00s)
PASSfunc ContainsAny(s, chars string) bool문자열 chars 의 임의 문자 unicode 코드가 문자열 s 내에 있는지 판단합니다. 즉 s 가 chars 내의 임의 문자열을 포함하는지 판단합니다.
func TestContainsAny(t *testing.T) {
fmt.Println(strings.ContainsAny("abcedfg", "bac"))
fmt.Println(strings.ContainsAny("abcedfg", "gfdecba"))
}=== RUN TestContainsAny
true
--- PASS: TestContainsAny (0.00s)
PASSfunc ContainsRune(s string, r rune) bool문자열 s 가 문자 r 을 포함하는지 판단합니다.
func TestContainsRune(t *testing.T) {
fmt.Println(strings.ContainsRune("abcedf", 'a'))
fmt.Println(strings.ContainsRune("abcedf", 'b'))
fmt.Println(strings.ContainsRune("你好世界", '你'))
}=== RUN TestContainsRune
true
true
true
--- PASS: TestContainsRune (0.00s)
PASS부분 문자열出現 횟수
func Count(s, substr string) int부분 문자열 substr 이 문자열 s 내에 나타난 횟수를 반환합니다.
func TestCount(t *testing.T) {
fmt.Println(strings.Count("3.1415926", "1"))
fmt.Println(strings.Count("there is a girl", "e"))
fmt.Println(strings.Count("there is a girl", ""))
}=== RUN TestCount
2
2
16
--- PASS: TestCount (0.00s)
PASS지정된 부분 문자열 삭제
func Cut(s, sep string) (before, after string, found bool)s 내에서 처음 나타난 부분 문자열 sep 을 삭제하고 삭제 후 결과를 반환합니다.
before- 삭제된 부분 문자열 위치 앞의 문자열after- 삭제된 부분 문자열 위치 뒤의 문자열found- 부분 문자열을 찾았는지 여부
func TestCut(t *testing.T) {
show := func(s, sep string) {
before, after, found := strings.Cut(s, sep)
fmt.Printf("Cut(%q, %q) = %q, %q, %v\n", s, sep, before, after, found)
}
show("Hello world", " ")
show("Hello world", "world")
show("Hello world", "Hello")
show("Hello world", "Hello world")
}=== RUN TestCut
Cut("Hello world", " ") = "Hello", "world", true
Cut("Hello world", "world") = "Hello ", "", true
Cut("Hello world", "Hello") = "", " world", true
Cut("Hello world", "Hello world") = "", "", true
--- PASS: TestCut (0.00s)
PASS대소문자 무시 동일
func EqualFold(s, t string) bool문자열 s 와 t 가 대소문자를 무시한 경우 동일한지 여부를 반환합니다.
func TestEqualFold(t *testing.T) {
fmt.Println(strings.EqualFold("你好", "你好"))
fmt.Println(strings.EqualFold("Hello", "Hello"))
fmt.Println(strings.EqualFold("Hello", "hELLO"))
}=== RUN TestEqualFold
true
true
true
--- PASS: TestEqualFold (0.00s)
PASS문자열 분할
func Fields(s string) []stringfunc FieldsFunc(s string, f func(rune) bool) []string전자는 공백을 기준으로 문자열을 분할하고, 후자는 함수 f 의 반환 값에 따라 분할 여부를 결정합니다.
func TestField(t *testing.T) {
fmt.Printf("%q\n", strings.Fields(" a b c d e f g "))
fmt.Printf("%q\n", strings.FieldsFunc("a,b,c,d,e,f,g", func(r rune) bool {
return r == ','
}))
}=== RUN TestField
["a" "b" "c" "d" "e" "f" "g"]
["a" "b" "c" "d" "e" "f" "g"]
--- PASS: TestField (0.00s)
PASS접두사/접미사 찾기
func HasPrefix(s, prefix string) boolfunc HasSuffix(s, suffix string) bool전자는 접두사를 찾고, 후자는 접미사를 찾습니다. 관심 있다면 소스 코드 구현을 확인해보세요. 꽤 흥미롭습니다.
func TestPreSuffix(t *testing.T) {
str := "abbc cbba"
fmt.Println(strings.HasPrefix(str, "abb"))
fmt.Println(strings.HasSuffix(str, "bba"))
}=== RUN TestPreSuffix
true
true
--- PASS: TestPreSuffix (0.00s)
PASS부분 문자열 위치
처음 나타난 부분 문자열의 인덱스를 반환합니다.
func Index(s, substr string) int처음 나타난 부분 문자열의 인덱스를 반환합니다.
func IndexAny(s, chars string) int처음 나타난 부분 문자열의 인덱스를 반환합니다.
func IndexRune(s string, r rune) int예시
func TestIndex(t *testing.T) {
fmt.Println(strings.Index("abcdefg", "bc"))
fmt.Println(strings.IndexAny("abcdefg", "cb"))
fmt.Println(strings.IndexRune("abcdefg", 'g'))
}=== RUN TestIndex
1
1
6
--- PASS: TestIndex (0.00s)
PASS마지막으로 나타난 부분 문자열의 인덱스를 반환합니다.
func LastIndex(s, substr string) int마지막으로 나타난 부분 문자열 임의 문자의 인덱스를 반환합니다.
func LastIndexAny(s, chars string) int예시
func TestLastIndex(t *testing.T) {
fmt.Println(strings.LastIndex("abcdefga", "a"))
fmt.Println(strings.LastIndexAny("abcdefghisa", "ba"))
}문자열 순회 및 교체
Map 은 문자열 s 의 사본을 반환하며 매핑 함수에 따라 문자열 s 의 모든 문자를 수정합니다. 매핑이 음수를 반환하면 해당 문자를 문자열에서 삭제하며 교체하지 않습니다.
func Map(mapping func(rune) rune, s string) string예시
func TestMap(t *testing.T) {
fmt.Println(strings.Map(func(r rune) rune {
return r - 32
}, "abcdefghijk"))
fmt.Println(strings.Map(func(r rune) rune {
return r + 32
}, "ABCDEFGHIJK"))
fmt.Println(strings.Map(func(r rune) rune {
if r < 'F' {
return -1
} else {
return r
}
}, "ABCDEFGHIJK"))
}출력
=== RUN TestMap
ABCDEFGHIJK
abcdefghijk
FGHIJK
--- PASS: TestMap (0.00s)
PASS문자열 반복 복제
주어진 count 에 따라 문자열을 복제하며, 음수이면 panic 이 발생합니다.
func Repeat(s string, count int) string예시
func TestRepeat(t *testing.T) {
fmt.Println(strings.Repeat("a", 10))
fmt.Println(strings.Repeat("abc", 10))
}출력
=== RUN TestRepeat
aaaaaaaaaa
abcabcabcabcabcabcabcabcabcabc
--- PASS: TestRepeat (0.00s)
PASS문자열 교체
s 는 원본 문자열, old 는 교체될 부분, new 는 old 의 교체 부분, n 은 교체 횟수입니다. n 이 0 보다 작으면 교체 횟수 제한이 없습니다.
func Replace(s, old, new string, n int) string예시
func TestReplace(t *testing.T) {
fmt.Println(strings.Replace("Hello this is golang", "golang", "c++", 1))
fmt.Println(strings.Replace("Hello this is golang", "o", "c", -1))
fmt.Println(strings.Replace("Hello this is golang", "o", "c", 1))
}출력
=== RUN TestReplace
Hello this is c++
Hellc this is gclang
Hellc this is golang
--- PASS: TestReplace (0.00s)
PASSReplace 의 유틸리티 함수로, strings.Replace(s, old, new, -1) 과 동일합니다.
func ReplaceAll(s, old, new string) string예시
func TestReplaceAll(t *testing.T) {
fmt.Println(strings.ReplaceAll("Hello this is golang", "o", "c++"))
}출력
=== RUN TestReplaceAll
Hellc++ this is gc++lang
--- PASS: TestReplaceAll (0.00s)
PASS문자열 분할
부분 문자열 sep 에 따라 문자열 s 를 문자열 슬라이스로 분할합니다.
func Split(s, sep string) []string부분 문자열 sep 에 따라 문자열 s 를 문자열 슬라이스로 분할하며, 분할 횟수는 n 에 따라 결정됩니다.
func SplitN(s, sep string, n int) []string부분 문자열 sep 에 따라 문자열 s 를 sep 를 포함하는 문자열 요소로 구성된 문자열 슬라이스로 분할합니다.
func SplitAfter(s, sep string) []string부분 문자열 sep 에 따라 문자열 s 를 sep 를 포함하는 문자열 요소로 구성된 문자열 슬라이스로 분할하며, 분할 횟수는 n 에 따라 결정됩니다.
func SplitAfterN(s, sep string, n int) []string예시
func TestSplit(t *testing.T) {
fmt.Printf("%q\n", strings.Split("this is go language", " "))
fmt.Printf("%q\n", strings.SplitN("this is go language", " ", 2))
fmt.Printf("%q\n", strings.SplitAfter("this is go language", " "))
fmt.Printf("%q\n", strings.SplitAfterN("this is go language", " ", 2))
}출력
=== RUN TestSplit
["this" "is" "go" "language"]
["this" "is go language"]
["this " "is " "go " "language"]
["this " "is go language"]
--- PASS: TestSplit (0.00s)
PASS대소문자 변환
영문 문자열을 소문자로 변환합니다.
func ToLower(s string) string전달된 해당 언어의 unicode.SpecialCase 에 따라 해당 언어의 소문자 문자열로 변환합니다.
func ToLowerSpecial(c unicode.SpecialCase, s string) string영문 문자열을 대문자로 변환합니다.
func ToUpper(s string) string전달된 해당 언어의 unicode.SpecialCase 에 따라 해당 언어의 대문자 문자열로 변환합니다.
func ToUpperSpecial(c unicode.SpecialCase, s string) string예시
func TestLowerAndUpper(t *testing.T) {
fmt.Println(strings.ToLower("My name is jack,Nice to meet you!"))
fmt.Println(strings.ToLowerSpecial(unicode.TurkishCase, "Önnek İş"))
fmt.Println(strings.ToUpper("My name is jack,Nice to meet you!"))
fmt.Println(strings.ToUpperSpecial(unicode.TurkishCase, "örnek iş"))
}출력
=== RUN TestLowerAndUpper
my name is jack,nice to meet you!
önnek iş
MY NAME IS JACK,NICE TO MEET YOU!
ÖRNEK İŞ
--- PASS: TestLowerAndUpper (0.00s)
PASS문자열 트리밍
문자열 양끝을 트리밍하여 cutset 과 일치하는 임의의 부분 문자열을 삭제합니다.
func Trim(s, cutset string) string문자열 왼쪽 끝을 트리밍하여 cutset 과 일치하는 임의의 부분 문자열을 삭제합니다.
func TrimLeft(s, cutset string) string문자열 왼쪽 끝 접두사를 트리밍하여 cutset 과 일치하는 부분 문자열을 삭제하며, 일치하지 않으면 문자열 s 를 반환합니다.
func TrimPrefix(s, suffix string) string문자열 오른쪽 끝을 트리밍하여 cutset 과 일치하는 임의의 부분 문자열을 삭제합니다.
func TrimRight(s, cutset string) string문자열 오른쪽 끝 접미사를 트리밍하여 cutset 과 일치하는 부분 문자열을 삭제하며, 일치하지 않으면 문자열 s 를 반환합니다.
func TrimSuffix(s, suffix string) string예시
func TestTrim(t *testing.T) {
fmt.Println(strings.Trim("!!this is a test statement!!", "!!!"))
fmt.Println(strings.TrimLeft("!!this is a test statement!!", "!!!"))
fmt.Println(strings.TrimRight("!!this is a test statement!!", "!!!"))
fmt.Println(strings.TrimPrefix("!!this is a test statement!!", "!!!"))
fmt.Println(strings.TrimSuffix("!!this is a test statement!!", "!!!"))
}출력
=== RUN TestTrim
this is a test statement
this is a test statement!!
!!this is a test statement
!!this is a test statement!!
!!this is a test statement!!
--- PASS: TestTrim (0.00s)
PASS문자열 Builder
문자열 Builder 는 문자열을 직접 조작하는 것보다 메모리를 더 절약합니다.
type Builder struct {
// 내부 필드는 외부에 노출되지 않음
}예시
func TestBuilder(t *testing.T) {
builder := strings.Builder{}
builder.WriteString("hello")
builder.WriteString(" world")
fmt.Println(builder.Len())
fmt.Println(builder.String())
}출력
=== RUN TestBuilder
11
hello world
--- PASS: TestBuilder (0.00s)
PASSTIP
Builder 를 값으로 전달하지 마십시오. 예를 들어 strings.Builder 를 함수 매개변수로 전달할 때 프로그램이 panic 합니다.
strings: illegal use of non-zero Builder copied by value내부에 다음과 같은 코드가 있습니다.
type Builder struct {
addr *Builder //자신의 주소
buf []byte
}
func (b *Builder) copyCheck() {
if b.addr == nil {
b.addr = (*Builder)(noescape(unsafe.Pointer(b)))
} else if b.addr != b {
panic("strings: illegal use of non-zero Builder copied by value")
}
}Builder 를 값으로 복사할 때 내부 슬라이스의 포인터도 복사되므로 두 Builder 가 문자열을 쓸 때 동일한 슬라이스를 조작하게 됩니다. 이것이 값 복사를 허용하지 않는 이유입니다.
문자열 Replacer
Replacer 는 문자열 교체에 사용됩니다.
func NewReplacer(oldnew ...string) *Replacer예시
func TestReplacer(t *testing.T) {
r := strings.NewReplacer("<", "<", ">", ">")
fmt.Println(r.Replace("This is <b>HTML</b>!"))
}출력
This is <b>HTML</b>!문자열 Reader
Reader 는 io.Reader, io.ReaderAt, io.ByteReader, io.ByteScanner, io.RuneReader, io.RuneScanner, io.Seeker, io.WriterTo 인터페이스를 구현합니다.
func NewReader(s string) *Reader예시
func TestReader(t *testing.T) {
reader := strings.NewReader("abcdefghijk")
buffer := make([]byte, 20, 20)
read, err := reader.Read(buffer)
if err != nil {
log.Panic(err)
}
fmt.Println(read)
fmt.Println(string(buffer))
}출력
=== RUN TestReader
11
abcdefghijk
--- PASS: TestReader (0.00s)
PASS