The Go Programming Language -앨런 도노반, 브라이언 커니건

2021. 6. 6. 11:16Books/Programmers

728x90
반응형

Hello, World

package main
import "fmt"
func main() {
    fmt.Println("Hello, World")
}
  • 작은 기본 구성 요소들을 모아 큰 프로그램을 만든다
  • 25개의 키워드가 있다.
  • 낙타 표기법(Camel case)을 사용한다. 밑줄 보다는 대문자를 더 선호
  • 선언에는 주로 var, const, type, func의 네 가지 종류가 있다.

 

변수

  • var 선언은 특정 타입의 변수를 만들고 이름을 붙인 뒤 초기 값을 설정
  • 값을 갖는 저장소 
    • var 이름 타입 = 표현식
    • 이름 := 표현식
// var 이름 타입 = 표현식
var s string
fmt.Println(s)
 
// 이름 := 표현식
freq := rand.Float64() * 3.0
t := 0.0
  • 변수의 수명
    • 변수의 수명은 프로그램이 실행될 때 변수가 존재하는 시간의 길이다
    • 패키지 수준 변수의 수명은 프로그램 전체 실행 기간과 동일
    • 지역 변수의 수명은 동적
    • 선언문이 실행될 때마다 새 인스턴스 생성

 

포인터

  • 변수의 주소, 포인터는 값이 저장돼 있는 위치
  • 변수의 주소를 취하거나 복사할 때마다 변수의 새 별명이나 동일한 변수를 식별할 수 있는 새로운 방법을 만든다
  • 변수에 접근 하려면 변수의 모든 별명까지 알아야 한다
// 
x := 1  // 변수
p := &x // 포인터 선언
*p = 2  // 주소 접근

 

new 함수

  • new(T) 표현식은 타입의 이름 없는 변수를 만들고 포인터 값인 변수의 주소를 반환한다
x := new(int)   // *int 타입 x는 이름 없는 int 변수를 가리킨다
fmt.Println(*p) // "0"

 

할당성

  • 함수 호출은 인자 값들을 그에 대응하는 파라미터들에 묵시적으로 할당
  • return 문은 return 문의 피연산자에 대응하는 반환
  • 할당문은 명시적이든 묵시적이든 왼쪽(변수)와 오른쪽(값)의 타입이 같으면 적법하다

 

배열

  • 0개 이상의 특정 타입 원소로 이뤄진 고정 길이 시퀀스
  • 고정 길이이기 때문에 직접 사용하는 경우가 거의 없다

 

슬라이스

  • 모든 원소가 같은 타입인 가변 길이 시퀀스
  • []T로 쓴다, 크기가 없는 배열 타입
  • 포인터, 길이, 용량 세 가지 구성 요소
  • 배열과 달리 비교할 수 없다
var s []int
len(s) == 0 //  슬라이스가 비어 있는지 확인 

//
var s = make([]int, 3)

// append, 슬라이스에 항목을 추가
var runes []rune
runes = append(runes, "3")

////  결과
[3]

 

  • 순서 없는 키/값 쌍의 모음
  • 모든 키는 별개이며 주어진 키와 관련된 값은 해시 테이블의 크기와 무관하게 평균적으로 일정한 회수의 키 비교를 통해 추출, 갱신, 제거할 수 있다
  • 맵은 해시 테이블의 참조
    • map[Key]Value
  •  graph
var graph = make(map[string]map[string]bool)
func addEdge(from, to string){
	edges := graph[from]
	if edges == nil{
		edges = make(map[string]bool)
		graph[from] = edges
	}
	edges[to] = true
}

func hasEdge(from, to string) bool{
	return graph[from][to]
}

 

구조체

  • 구조체는 0개 이상의 명명된 임의의 타입 값을 하나의 개체로 모으는 집합형 데이터 타입
  • 각 값은 필드라 한다. 
  • 개체 단위로 복사, 함수 전달, 반환, 배열에 저장 등 할 수 있다.
  • 구조체 리터럴
// 명확한 순서가 있는 구조체에 명시
type Point struct{ X, Y int}
p := Point{1, 2}

// 필드가 연관되는 값 목록으로 초기화
type VertexStruct struct{ X, Y int }
mv := make(map[string]VertexStruct)
mv["v1"] = VertexStruct{X: 10, Y: 20}
fmt.Println(mv["v1"])

 

JSON

  • 자바스크립트 객체 표기법
  • 자바스크립트 값을 유니코드 텍스트로 인코딩한 것
  • 마샬링, Data 구조 → json
// 데이터 구조를 JSON으로 변환
type Movie struct{
	Title string
	Year int `json:"released"`
	Color bool `json:"color,omitempty"`
	Actors []string
} 
var movies = []Movie{
	{Title: "Casab", Year: 1942, Color: false, Actors: []string{"A","B"},
	{Title: "Casab2", Year: 1952, Color: false, Actors: []string{"C","B"},
} 
//data, err := json.Marshal(movies)
data, err := json.MarshalIndent(movies, "", " ") // 좀 더 깔끔하게 들여쓰기 한 결과 제공
if err != nil{
	log.Fatalf("JSON error marshaling : %s", err)
}
fmt.Printf("%s\n", data)

 

defer

  • 연기된 함수
func sum(vals ...int) int{
	total := 0
	for _, val := range vals{
		total += val
	}
 	fmt.Println(sum)
	return total
}

defer sum(1,2,3)
sum(1,2,3,4,5)

//// 결과
15
6

 

인터페이스

  • 다른 타입의 동작을 일반화 하거나 추상화해서 표현
  • 함수를 특정 구현의 세부 사항에 구애받지 않고 더 유연하고 융통성 있게 작성 가능
  • 인터페이스 타입은 구상 타입이 해당 인터페이스의 인스턴스로 인식되기 위해 필요한 메소드들을 지정
  • 종종 인터페이스의 집합부터 만들고 나중에 인터페이스를 충족하는 구상 타입을 정의
  • 인터페이스는 두 개 이상의 타입을 충족할 때에만 사용되므로 특정 구현을 추상화 하기 위해 반드시 필요
type MyFloat float64

type Vertex struct {
	X, Y float64
}

type Abser interface {
	Abs() float64
}

func (f MyFloat) Abs() float64 {
	if f < 0 {
		return float64(-f)
	}
	return float64(f)
}

func (v *Vertex) Abs() float64 {
	return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

var a Abser
f := MyFloat(-math.Sqrt2)
v := Vertex{3, 4}

a = f
fmt.Println(a.Abs()) // a MyFloat implements
a = &v
fmt.Println(a.Abs()) // a *Vertex implements
// a = v // dose not implement Abser!

//// 결과
1.4142135623730951
5

 

고루틴

  • 독립적인 작업(goroutine)간에 값을 전달
  • 동시에 수행되는 작업
//     
func say(s string) {
	for i := 0; i < 5; i++ {
		time.Sleep(100 * time.Millisecond)
		fmt.Println(s)
	}
}  

go say("world")
say("hello")

//// 결과
hello
world
hello
world
hello
world
world
hello
hello

 

채널

  • 고루틴 간의 연결
  • 한 고루틴이 다른 고루틴으로 값을 보내기 위한 통신 메커니즘
  • 채널을 복사하거나 함수의 인자로 전달할 때, 참조를 복사, 호출자와 피호출자는 같은 데이터 구조를 참조
    • ch ← x     //송신 구문
      x = ← ch // 할당문 안의 수신 표현식
      ← ch       //수신 구문, 결과는 버려짐
func sum(s []int, c chan int) {
	sum := 0
	for _, v := range s {
		sum += v
	}
	c <- sum // send sum to c
}

s := []int{7, 2, 8, -9, 4, 0}

c := make(chan int)
go sum(s[:len(s)/2], c)
go sum(s[len(s)/2:], c)
x, y := <-c, <-c // receive from c

fmt.Println(x, y, x+y)

//// 결과
-5 17 12
  • close는 이 채널에 더 이상 값을 보내지 않음을 나타내는 플래그
    • close(ch)
    • 수신된 채널 요소 및 보통 ok로 부르며 수신에 성공하면 true, 닫혔거나 소진된 채널에서 수신하면 false를 반환
728x90
반응형