Sad Puppy 3 [묘공단] Go언어 기초 15-17장(문자열, 패키지) :: 개발자 아지트

문자열

 

  • 문자열 표현법
  • UTF-8 구조
  • 문자열 동작 원리 

 

go언어에서는 UTF-8 문자코드를 사용함(한글이나 한자 사용에 문제 없음)

UTF-8문자 코드는 유니코드로써, 가변 길이 문자 인코딩 방식임

 

 

go언어에서 문자열은 큰따옴표나 백쿼드(`)로 묶어 표시한다. 

 

package main

import (
	"fmt"
)

func main() {
	str := "내 이름은 \t'김정자'\n"

	fmt.Println(str)

	str2 := `"야 내 이름은", 김 정 자 야. ^^`
    // 백쿼트로 문자열을 묶을 경우, 특수 문자가 동작하지 않음
	fmt.Println(str2)
}

// 큰 따옴표를 통해 여러 줄 표현시 \n을 사용해야함
// 백쿼트를 통해 여러 줄 표현시 아무것도 필요 없음

 

 

UTF-8문자 코드 

 

다국어 문자를 지원하고, 자주 사용되는 영문자나 숫자 등 일부 특수 문자를 1바이트로 표현함. 

(그 외의 다른 문자들은 2~3바이트로 표현)

ANSI 코드와 1:1대응이 가능하여, 바로 변환된다는 장점이 있음 

 

 

문자를 사용하는 경우 - rune 타입 사용

 

go에서는 문자 하나만 표현할 때 rune타입을 사용함

UTF-8 문자 값은 3바이트로 이루어져 있음, Go에서 문자 표현시 3바이트 정수 타입은 제공하지 않으므로, 4바이트 정수 타입인 int32타입의 별칭 타입인 rune타입을 사용해야함. 

 

package main

import (
	"fmt"
)

func main() {
	var chr rune = '야'
	// 사실 rune 타입은 int32타입과 같은 타입임
	fmt.Printf("%T\n", chr) // int32 출력
	fmt.Printf("%c", chr)   // 야 출력
	fmt.Println(chr)        // 50556 출력(chr 값)
}

 

 

len()으로 문자열이 차지하는 메모리 크기(문자열 크기를 확인)를  할 수 있음

 

package main

import (
	"fmt"
)

func main() {
	// 문자열은 아래와 같이 각 문자의 코드 값의 배열로 나타낼 수 있음 
	runes := []rune{72, 101, 108, 108}
	fmt.Println(string(runes)) // Hell

}

 

 

또한 string타입과 []byte 타입 간 상호 변환이 가능하다. 

 

문자열 순회는 byte단위로 한글자씩 순회하거나,

[]rune 타입으로 변환 후 한 글자씩 순회하거나, 반복문을 통해 순환할 수 있다. 

 

파이썬과 같이 문자열 연산은 +, += 연산자, 같은지 비교시 ==, !=를 사용할 수 있다. 

문자열에 대한 대소 비교시, >, <, >=, <=를 사용하고, 첫 글자부터 하나 씩 값 비교해서 유니코드 값을 비교함 

 

 

문자열 구조

 

type StringHeader struct {
	Data uintptr // 문자열의 데이터가 있는 메모리 주소를 나타냄 = 포인터
    Len int // 문자열의 길이 
}

 

만약 string끼리 대입할 경우, 대입 대상 변수에 기존 변수의 data, len값만 복사됨(= 문자열 자체는 복사되지 않음)

 

Go언어에서 string타입의 문자열의 전체는 변경 가능하지만, 일부만 변경할 수 없다. 

만약, string타입을 슬라이스 타입으로 타입 변경후(기존 문자열의 주소와는 다른 주소를 가리키는 상태로 변경), 일부 문자를 변경한 후 출력한다면 해당 문자열은 변경후 출력 가능함. 

 

문자열을 합산할 경우, 만약 문자열 a와 문자열 b가 있으면, 문자열 a와 b를 합친 문자열 c가 생성됨(a, b, c의 모든 메모리 주소는 서로 다른곳을 가리킴)

문자열 합산이 자주 일어날경우, 메모리가 낭비됨. 

이런 경우 strings패키지의 Builder을 이용하는 방법이 있음.

 

go에서 이렇게 하는 이유는, 버그를 방지하기 위함임 

 

패키지

  • 패키지 정의
  • 외부 패키지 사용하기
  • Go 모듈 알아보기 

 

패키지는 코드를 묶는 최대 단위임.

Go로 만든 모든 프로그램은 패키지를 묶어 만들게됨. 패키지를 통해 함수, 구조체, 상수 등을 외부에서 사용할 수 있음

 

함수를 통해 코드 블록을 묶고, 구조체로 데이터들을 묶고, 패키지를 통해 함수와 구조체 등 그외의 코드들을 묶음.

main 패키지는 다른 패키지들과는 다르게 프로그램의 시작점을 포함한 패키지임. 

 

Go의 프로그램은 main 패키지(필수)하나와 그 외 여러 외부 패키지(선택)으로 구성됨. 

 

 

그 외 여러 외부 패키지는 외부에서 가져다 쓰는 라이브러리와 같다. 

 

패키지 찾는 곳

https://golang.org/pkg/ 

 

Standard library - Go Packages

Discover Packages Standard library Version: go1.22.1 Opens a new window with list of versions in this module. Published: Mar 5, 2024 License: BSD-3-Clause Opens a new window with license information. Jump to ... Directories Directories ¶ Show internal Exp

pkg.go.dev

위 사이트를 통해 표준 패키지 목록 확인이 가능함

 

Go언어에서 많이 사용되는 패키지는 Awesome Go에서 찾아보면 좋다. 

https://github.com/avelino/awesome-go 

 

GitHub - avelino/awesome-go: A curated list of awesome Go frameworks, libraries and software

A curated list of awesome Go frameworks, libraries and software - avelino/awesome-go

github.com

 

 

패키지 사용하기 

 

// import 예약어로 임포트 하고, 원하는 패키지 경로를 따옴표로 묶어 써줌
import "fmt"

 

import {
	"fmt"
    "os"
}

 

이런식으로 다른 패키지를 가져오면 가져온 패키지에서 외부로 노출하는 함수나 구조체, 변수, 상수 등을 사용할 수 있음

 

외부 노출 여부는 이름의 첫 글자가 대문자면 노출한다는 의미이다. 

패키지 명은 가져오는 패키지 경로의 가장 마지막 폴더이름이다. 

 

fmt.Println("hi")

 

패키지를 통한 호출은 .을 통해 할 수 있다. 

 

package main

import ( // 둘이상의 패키지는 소괄호로 묶어줌
	"fmt"
	"math/rand" // 경로가 있는 패키지 사용
)

func main() { 
	fmt.Println(rand.Int()) // 경로가 있는 패키지 접근시 마지막 폴더명만 사용함
}

 

 

패키지 명이 겹칠경우, 별칭을 주어 구분한다. 

 

import {
	"text/template" // template 패키지
    "html/template" // 역시 같은 이름의 template 패키지
}

 

별칭을 쓸 경우 패키지명 앞에 사용

 

import (
	"text/template" // template 패키지
    htemplate "html/template" // 별칭 htemplate, 해당 패키지는 htemplate로 사용 가능함
)

 

사용하지 않는 패키지를 포함해야 하는 경우, 패키지 앞에 _ 을 붙여준다. 

 

 

import로 패키지를 포함시킬 경우, go build를 통해 파일을 빌드할 때, 해당 패키지를 찾아서 포함한 후 실행 파일을 생성함

해당 패키지는 다음과 같은 경로에서 확인할 수 있다. 

 

1. Go 설치 경로

2. GOPATH\pkg

3. 현재 폴더 아래의 위치

 

Go 모듈

Go 모듈은 Go 패키지들을 모아놓은 Go 프로젝트 단위이다. 

Go 1.16 버전부터 Go모듈 사용이 기본이 됨.

이전까지의 Go 코드는 GOPATH/src 폴더 아래에 있어야 했지만, Go 모듈이 기본이 되면서 모든 Go 코드는 Go모듈 아래에 위치해야

 

go build를 위해서, Go 모듈 루트 폴더에 go.mod파일이 있어야함.

go.mod 파일에는 모듈 이름, Go 버전, 필요한 외부 패키지 등이 명시되어 있음 

 

Go언어에서 go build를 통해 실행 파일을 만들 때, 

 go.mod와 go.sum(외부 저장소 패키지 버전 정보를 담고있음) 파일을 통해 외부 패키지와 모듈 내 패키지를 합쳐서 만듦

 

go mod init [패키지명]

 

위 명령어 실행시 go.mod파일이 생성됨 

 

히히 실습 완료

 

 

패키지를 만들때

Go언어에서 패키지명을 만들때, 쉽고 간결하게 이름 짓기를 권장한다. 

모든 문자를 소문자로 할 것을 권장한다. 

 

패키지 초기화

패키지를 임포트 할 때, 컴파일러는 패키지 내 전역변수를 초기화 한다. 그 후, 패키지에 init()함수가 있다면 호출해서 패키지를 초기화 한다. init()함수는 입력 매개변수가 없고, 반환값이 없는 함수여야 한다. 

 

 

해당 글은 [Tucker의 Go 언어 프로그래밍] 15장~17장을 읽고 공부한 글입니다. 

 

+ Recent posts