Skip to content

strings

strings 패키지는 UTF-8 인코딩 문자열을 조작하는 간단한 함수를 구현합니다. 간단히 말해 문자열 조작을 위한 유틸리티 패키지입니다.

공식 문서: strings package - strings - Go Packages

TIP

Go 는 기본적으로 UTF8 문자를 지원하며, 모든 문자열 조작은 UTF8 을 기반으로 합니다.

가져오기

go
import (
   "strings"
)

아래에서는 예시를 통해 자주 사용되는 함수를 설명하겠습니다.

문자열 복제

go
func Clone(s string) string

복제된 사본에 새 메모리를 할당하며, 빈 문자열을 전달하면 메모리를 할당하지 않고 빈 문자열을 반환합니다.

go
func TestClone(t *testing.T) {
   ori := "hello 世界"
   copys := strings.Clone(ori)
   fmt.Println(ori, copys)
   fmt.Println(&ori, &copys)
}
=== RUN   TestClone
hello 世界 hello 世界
0xc00005e5d0 0xc00005e5e0
--- PASS: TestClone (0.00s)
PASS

문자열 비교

go
func Compare(a, b string) int

a 와 b 를 사전 순으로 문자열 비교하며, a>b 이면 1 을 반환하고, a<b 이면 -1 을, a=b 이면 0 을 반환합니다.

go
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

문자열 포함

go
func Contains(s, substr string) bool

문자열 s 가 부분 문자열 substr 을 포함하는지 판단합니다.

go
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)
PASS
go
func ContainsAny(s, chars string) bool

문자열 chars 의 임의 문자 unicode 코드가 문자열 s 내에 있는지 판단합니다. 즉 s 가 chars 내의 임의 문자열을 포함하는지 판단합니다.

go
func TestContainsAny(t *testing.T) {
  fmt.Println(strings.ContainsAny("abcedfg", "bac"))
  fmt.Println(strings.ContainsAny("abcedfg", "gfdecba"))
}
=== RUN   TestContainsAny
true
--- PASS: TestContainsAny (0.00s)
PASS
go
func ContainsRune(s string, r rune) bool

문자열 s 가 문자 r 을 포함하는지 판단합니다.

go
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

부분 문자열出現 횟수

go
func Count(s, substr string) int

부분 문자열 substr 이 문자열 s 내에 나타난 횟수를 반환합니다.

go
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

지정된 부분 문자열 삭제

go
func Cut(s, sep string) (before, after string, found bool)

s 내에서 처음 나타난 부분 문자열 sep 을 삭제하고 삭제 후 결과를 반환합니다.

  • before - 삭제된 부분 문자열 위치 앞의 문자열
  • after - 삭제된 부분 문자열 위치 뒤의 문자열
  • found - 부분 문자열을 찾았는지 여부
go
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

대소문자 무시 동일

go
func EqualFold(s, t string) bool

문자열 s 와 t 가 대소문자를 무시한 경우 동일한지 여부를 반환합니다.

go
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

문자열 분할

go
func Fields(s string) []string
go
func FieldsFunc(s string, f func(rune) bool) []string

전자는 공백을 기준으로 문자열을 분할하고, 후자는 함수 f 의 반환 값에 따라 분할 여부를 결정합니다.

go
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

접두사/접미사 찾기

go
func HasPrefix(s, prefix string) bool
go
func HasSuffix(s, suffix string) bool

전자는 접두사를 찾고, 후자는 접미사를 찾습니다. 관심 있다면 소스 코드 구현을 확인해보세요. 꽤 흥미롭습니다.

go
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

부분 문자열 위치

처음 나타난 부분 문자열의 인덱스를 반환합니다.

go
func Index(s, substr string) int

처음 나타난 부분 문자열의 인덱스를 반환합니다.

go
func IndexAny(s, chars string) int

처음 나타난 부분 문자열의 인덱스를 반환합니다.

go
func IndexRune(s string, r rune) int

예시

go
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

마지막으로 나타난 부분 문자열의 인덱스를 반환합니다.

go
func LastIndex(s, substr string) int

마지막으로 나타난 부분 문자열 임의 문자의 인덱스를 반환합니다.

go
func LastIndexAny(s, chars string) int

예시

go
func TestLastIndex(t *testing.T) {
  fmt.Println(strings.LastIndex("abcdefga", "a"))
  fmt.Println(strings.LastIndexAny("abcdefghisa", "ba"))
}

문자열 순회 및 교체

Map 은 문자열 s 의 사본을 반환하며 매핑 함수에 따라 문자열 s 의 모든 문자를 수정합니다. 매핑이 음수를 반환하면 해당 문자를 문자열에서 삭제하며 교체하지 않습니다.

go
func Map(mapping func(rune) rune, s string) string

예시

go
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"))
}

출력

text
=== RUN   TestMap
ABCDEFGHIJK
abcdefghijk
FGHIJK
--- PASS: TestMap (0.00s)
PASS

문자열 반복 복제

주어진 count 에 따라 문자열을 복제하며, 음수이면 panic 이 발생합니다.

go
func Repeat(s string, count int) string

예시

go
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 보다 작으면 교체 횟수 제한이 없습니다.

go
func Replace(s, old, new string, n int) string

예시

go
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)
PASS

Replace 의 유틸리티 함수로, strings.Replace(s, old, new, -1) 과 동일합니다.

go
func ReplaceAll(s, old, new string) string

예시

go
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 를 문자열 슬라이스로 분할합니다.

go
func Split(s, sep string) []string

부분 문자열 sep 에 따라 문자열 s 를 문자열 슬라이스로 분할하며, 분할 횟수는 n 에 따라 결정됩니다.

go
func SplitN(s, sep string, n int) []string

부분 문자열 sep 에 따라 문자열 s 를 sep 를 포함하는 문자열 요소로 구성된 문자열 슬라이스로 분할합니다.

go
func SplitAfter(s, sep string) []string

부분 문자열 sep 에 따라 문자열 s 를 sep 를 포함하는 문자열 요소로 구성된 문자열 슬라이스로 분할하며, 분할 횟수는 n 에 따라 결정됩니다.

go
func SplitAfterN(s, sep string, n int) []string

예시

go
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

대소문자 변환

영문 문자열을 소문자로 변환합니다.

go
func ToLower(s string) string

전달된 해당 언어의 unicode.SpecialCase 에 따라 해당 언어의 소문자 문자열로 변환합니다.

go
func ToLowerSpecial(c unicode.SpecialCase, s string) string

영문 문자열을 대문자로 변환합니다.

go
func ToUpper(s string) string

전달된 해당 언어의 unicode.SpecialCase 에 따라 해당 언어의 대문자 문자열로 변환합니다.

go
func ToUpperSpecial(c unicode.SpecialCase, s string) string

예시

go
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 과 일치하는 임의의 부분 문자열을 삭제합니다.

go
func Trim(s, cutset string) string

문자열 왼쪽 끝을 트리밍하여 cutset 과 일치하는 임의의 부분 문자열을 삭제합니다.

go
func TrimLeft(s, cutset string) string

문자열 왼쪽 끝 접두사를 트리밍하여 cutset 과 일치하는 부분 문자열을 삭제하며, 일치하지 않으면 문자열 s 를 반환합니다.

go
func TrimPrefix(s, suffix string) string

문자열 오른쪽 끝을 트리밍하여 cutset 과 일치하는 임의의 부분 문자열을 삭제합니다.

go
func TrimRight(s, cutset string) string

문자열 오른쪽 끝 접미사를 트리밍하여 cutset 과 일치하는 부분 문자열을 삭제하며, 일치하지 않으면 문자열 s 를 반환합니다.

go
func TrimSuffix(s, suffix string) string

예시

go
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 는 문자열을 직접 조작하는 것보다 메모리를 더 절약합니다.

go
type Builder struct {
  // 내부 필드는 외부에 노출되지 않음
}

예시

go
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)
PASS

TIP

Builder 를 값으로 전달하지 마십시오. 예를 들어 strings.Builder 를 함수 매개변수로 전달할 때 프로그램이 panic 합니다.

strings: illegal use of non-zero Builder copied by value

내부에 다음과 같은 코드가 있습니다.

go
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 는 문자열 교체에 사용됩니다.

go
func NewReplacer(oldnew ...string) *Replacer

예시

go
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 인터페이스를 구현합니다.

go
func NewReader(s string) *Reader

예시

go
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

Golang by www.golangdev.cn edit