Notice
Recent Posts
Recent Comments
Link
250x250
반응형
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |
Tags
- 커뮤니티 탐지
- cypher 쿼리
- n8n
- 자격증
- cypher팁
- go best practices
- concurrency
- Golang
- 엔터티
- cypher쿼리
- 그래프데이터베이스
- SQLD
- GraphDB
- 정리
- 쿼리프로파일링
- Database
- basic golang
- neo4j성능
- 그래프 데이터베이스
- token bucket
- arangodb
- 프로그래밍
- go
- cypher
- graph
- 고루틴
- Neo4j
- apoc 라이브러리
- 중심성 측정
- 데이터모델링
Archives
- Today
- Total
Jamie the programmer
[Golang] 기본적으로 알아야할 기초 지식 part2 본문
Contents
접기
◎ 실전 Go 프로젝트에 투입되기 전에 사전에 알아야할 Go 언어의 기본 및 필수 개념을 설명해 드립니다.
¶ 이번 글에서 다룰 내용은 다음과 같습니다.
1. 문자열
2. 구조체
3. 함수
4. 메서드
이어지는 다음글 [Golang] 기본적으로 알아야할 기초 지식 part3 에서는 고루틴, 채널, 컨텍스트 를 다루겠습니다.
1. 문자열
1.1. 문자열 변환
문자열은 유니코드 문자의 코드값을 정수로 표현한 값(rune 또는 int32)의 시퀀스이므로,
[]rune (또는 []int32)으로 변환할 수 있습니다.
- 1바이트로 표현할 수 있는 아스키 문자열은 []byte(또는 []uint8)로 변환할 수 있다. 아스키가 아닌 문자열을 []byte로 변환하면 잘못된 코드값으로 변환될 수 있으니 주의해야 합니다.
[]rune(s) | 문자열 s를 유니코드 문자의 코드값 배열( []rune 또는 []int32 )로 변환 |
[]byte(s) | 문자열 s를 바이트 배열( []byte 또는 []uint )로 변환 |
string(chars) | 유니코드 문자의 코드값 배열( []rune 또는 []int32 )을 문자열로 변환 |
string(i) | 유니코드의 코드 포인트 i를 문자열로 변환(i가 65라면 “A”로 변환) |
s1 := "hello"
fmt.Println([]rune(s1)) // [104 101 108 108 111]
fmt.Println([]byte(s1)) // [104 101 108 108 111]
fmt.Println(string([]byte{104, 101, 108, 108, 111})) // hello
fmt.Println(string([]rune{104, 101, 108, 108, 111})) // hello
s2 := "안녕하세요"
fmt.Println([]rune(s2)) // [50504 45397 54616 49464 50836]
fmt.Println([]byte(s2)) // [236 149 136 235 133 149 237 149 152 236 132 184 236 154 148]
// 안녕하세요
fmt.Println(string([]rune{50504, 45397, 54616, 49464, 50836}))
// 안녕하세요
fmt.Println(string([]byte{236, 149, 136, 235, 133, 149, 237, 149, 152, 236, 132, 184, 236, 154, 148}))
fmt.Println(string(104)) // h
fmt.Println(string(236)) // ì
fmt.Println(string(50504)) // 안
fmt.Println(string([]byte{236, 149, 136})) // 안
1.2. 문자열 길이
- 문자열의 바이트 수를 구할 때는 len() 함수를 사용합니다.
- 바이트가 아니라 문자열의 내부 문자 수를 구할 때는 unicode/utf8 패키지의 utf8.RuneCountInString() 함수를 사용하거나,
문자열을 []rune 타입으로 변환하고 변환한 값의 길이( len([] rune()) )를 구하면 됩니다.
package main
import (
"fmt"
"unicode/utf8"
)
func main() {
s1 := "hello"
s2 := "안녕하세요"
fmt.Println(len(s1)) // 5
fmt.Println(len(s2)) // 15
fmt.Println(utf8.RuneCountInString(s2)) // 5
fmt.Println(len([]rune(s2))) // 5
}
2. 구조체
2.1. 구조체란?
다른 타입의 값들을 변수 하나로 묶어주는 기능입니다.
type 타입명 struct {
필드명 타입
…
필드명 타입
}
- 타입명의 첫 번째 글자가 대문자이면 패키지 외부로 공개 되는 타입입니다
3. 함수
3.1. 함수란?
- 함수란 특수한 코드 묶음을 말합니다.
- 함수는 함수 키워드, 함수명, 매개변수, 반환타입, 함수 코드 블록으로 구성됩니다.
- 함수를 만들면 코드를 재사용할 수 있습니다.
- 함수를 이용해서 중복 코드를 제거하여 코드를 간결하게 만들 수 있습니다.
- 자주 사용되거나 변경 가능성이 있는 코드 블록을 묶어서 함수를 만들면 효율적으로 코딩할 수 있고 추후 프로그램 변경 요구에도 간단히 대처할 수 있습니다.
- 또 관련된 코드를 묶어서 이름을 부여하기 때문에 코드를 읽기에도 훨씬 편해집니다.
3.2. 함수 호출
3.2.1. 인수; 아규먼트; argument
함수를 호출할 때 입력하는 값
3.2.2. 매개변수; 파라미터; parameter
함수가 외부로 부터 입력 받는 변수
3.3. 인수는 매개변수로 복사된다
함수를 호출 하며 입력한 값은 실제 함수에 보낸 값을 그대로 사용하는 것이 아니라 값을 복사해 사용하게 됩니다.
3.4. 함수 호출 Flow
- Add() 함수를 호출합니다.
- 매개별수를 선언하고 입력한 인숫값을 복사합니다.
- return 키워드를 사용해서 함수 결과가 반환됩니다.
- 반환된 값은 함수가 호출된 곳을 대체하는 것과 같습니다.
- 호출한 함수가 종료되면 함수에서 사용한 지역 변수에 접근할 수 없으며 return으로 함수 결과가 반환되면서 함수가 즉시 종료되어 함수를 호출했던 호출 위치로 명령 포인터가 되돌아가서 수행됩니다.
- c에 반환값이 대입(복사)됩니다.
3.5. Go 언어는 값전달만 지원합니다
Go를 심플하고 일관적인 언어라고 말하는 이유 중 변수 전달이 항상 복사로만 이뤄지기 때문도 있습니다.
3.6. 함수의 활용 - 함수의 자료형, 함수객체, 익명함수, 클로져
3.6.1. 함수의 자료형
func add(a int, b int) int {
return a+b
}
func sub(a int, b int) int {
return a-b
}
func main() {
var f func(int, int) int
a, b := 5, 4
f = add
fmt.Println(f(a,b))
f = sub
fmt.Println(f(a,b))
}
3.6.2. 함수객체
func SomeFunc() {
printNum := func(i int) {
fmt.Printf("It is %d\n", i)
}
i := 3
printNum(i)
}
3.6.3. 익명함수
func main() {
var wg sync.WaitGroup
ch := make(chan int, 10)
for i := 0; i < 10; i ++ {
ch <- i
wg.Add(1)
go func() {
fmt.Printf("Job %d finished.\n", <-ch)
wg.Done()
}()
}
wg.Wait()
}
3.6.4. 클로져
type Product struct {
Identifier int
Name string
User string
}
func (p Product) Info() string {
return fmt.Sprintf("%s (ID:%d), owned by %s", p.Name, p.Identifier, p.User)
}
func Factory(name string) func(string) Product {
p := Product{}
p.Name = name
i := 0
return func(user string) Product {
p.Identifier = i
p.User = user
i ++
return p
}
}
func main() {
airpods := Factory("air-pods")
buzz := Factory("galaxy-buzz")
p := airpods("Park")
fmt.Println(p.Info())
l := airpods("Lee")
fmt.Println(l.Info())
k := buzz("Kim")
fmt.Println(k.Info())
j := airpods("Jeong")
fmt.Println(j.Info())
}
4. 메서드
4.1. 메서드란?
- 메서드(method)는 함수의 일종입니다.
- Go 언어에는 클래스가 없습니다.
그래서 구조체 밖에 메서드를 지정합니다.
구조체 밖에 메소드를 정의할 때 리시버라는 특별한 기능을 사용합니다.
func (r Rabbit) info() int {
return r.width * r.height
}
4.1.1. 효과
- 메서드를 사용해서 데이터와 기능을 묶어 응집도를 높입니다.
- 코드 재사용성을 높입니다.
- 모듈화로 코드의 가독성이 좋아집니다.
4.1.2. 리시버란?
리시버는 메서드가 속하는 타입을 알려주는 기법입니다.
- 구조체 밖에 메서드가 있으므로 메서드가 어느 구조체에 속하는지 표시할 방법이 필요합니다.
- 구조체에서 필드가 해당 구조체에 속하듯이 메서드는 해당 리시버 타입에 속합니다.
4.2. 함수 & 메서드 차이점
- 리시버가 있으면 메서드, 없으면 일반 함수입니다.
- 호출 방법이 다릅니다
4.3. 메서드 선언
메서드를 선언하려면 리시버를 func 키워드와 함수 이름 사이에 소괄호로 명시해야 합니다
- info() 메서드가 Rabbit 타입에 속한다는 것을 알 수 있습니다.
- 구조체 변수(r)는 해당 메서드에서 매개변수처럼 사용됩니다.
- 리시버로는 모든 로컬 타입들이 가능한데, 로컬 타입이란 해당 패키지 안에서 type 키워드로 선언된 타입들을 말합니다.
- 그래서 패키지 내 선언된 구조체, 별칭 타입들이 리시버가 될 수 있습니다.
- 메서드 정의는 같은 패키지 내 어디에도 위치할 수 있습니다.
- 하지만 리시버 타입이 선언된 파일 안에 정의하는 게 일반적인 규칙입니다.
4.4. 메서드 호출
구조체의 필드에 접근할 때처럼 점(.) 연산자를 사용해해당 타입에 속한 메서드를 호출할 수 있습니다.
package main
import "fmt"
type Rabbit struct {
width int
height int
}
func (r Rabbit) info() int {
return r.width * r.height
}
func main() {
rabbit := &Rabbit{5, 6}
size := rabbit.info()
fmt.Println(size)
}
이어지는 다음글 [Golang] 기본적으로 알아야할 기초 지식 part3 에서는 고루틴, 채널, 컨텍스트 를 다루겠습니다.
728x90
반응형
'programming > golang' 카테고리의 다른 글
Go에서 Throttling과 Debouncing? 요청은 줄이고 효율은 높이자! (0) | 2025.03.10 |
---|---|
고루틴도 편히 쉬어야 한다! Go에서 Graceful Shutdown 구현하기 (0) | 2025.03.10 |
Go 언어, 이렇게 쓰면 GOAT 된다 - 실전 꿀팁 12개! (0) | 2025.03.10 |
Go 코드에서 UML 다이어그램 뽑아내기 – 개발자 생산성 200% UP! (0) | 2025.03.07 |
[Golang] 기본적으로 알아야할 기초 지식 part1 (0) | 2023.06.24 |