본문 바로가기
Go

A Tour of Go

by monsangter 2023. 5. 18.

-welcome

 

인터넷에 끊겨 있더라도 로컬에서 실행 가능하다.

 

go install golang.org/x/website/tour@latest

2009 11 10 23Z 에 이 웹 고 환경은 시작 되 었다.

cpu 나 메모리 사용 제한이 있으며, 외부 네트워크 호스트와 연결 안됨.

 

-packages

 

package main

import (
	"fmt"
	"math/rand"
)

func main() {
	fmt.Println("My favorite number is", rand.Intn(10))
}

fmt는 표준 입출력 패키지.

패키지를 불러와 사용할땐 임포트 패스의 마지막 앨리먼트, 그러니까 math/rand로 불러온건

rand.Intn처럼 사용한다.

 

-imports

import (
	"fmt"
	"math"
)

보통 parenthesize로 fator해서 표현한다.

 

import "fmt"
import "math"

다음과 같은 표현도 가능.하지만 보통 팩터함!

 

-exported names

 

pakages에서 export 하기 위해선 보통 대문자로 시작함.

package main

import (
	"fmt"
	"math"
)

func main() {
	fmt.Println(math.pi)
}

To fix the error, rename math.pi to math.Pi and try it again.

 

-functions

package main

import "fmt"

func add(x int, y int) int {
	return x + y
}

func main() {
	fmt.Println(add(42, 13))
}

0에서 다수의 매개변수 를 받는다.

 

보통 타입은 변수명 뒤에온다.

 

-functions continued

 

x int, y int

와 같이 함수매개변수가 연속적으로 타입을 공유하면 생략할 수 있으며, 마지막에만 하나 적는다.

 

x, y int

 

-multiple results

 

함수는 다수개의 결과를 리턴할 수 있다.

package main

import "fmt"

func swap(x, y string) (string, string) {
	return y, x
}

func main() {
	a, b := swap("hello", "world")
	fmt.Println(a, b)
}

-named return values, naked return

 

함수 최상단에 변수 선언처럼 리턴 값들을 지정해줄 수 있다. 

func split(sum int) (x, y int) {
	x = sum * 4 / 9
	y = sum - x
	return
}

naked return 이라고 불리며 가독성을 해칠 수 있기에 일반적으로 짧은 함수에서 사용한다.

 

-variables

 

함수 인자와 마찬가지로 비슷하게 변수 선언한다. 다만 앞에 var을 붙이고 타입이 마지막에 옴.

패키지 레벨에서나 함수 레벨에서나 모두 선언할 수 있다.

 

package main

import "fmt"

var c, python, java bool

func main() {
	var i int
	fmt.Println(i, c, python, java)
}

- 초기화와 변수

 

초기화자가 존재하는 경우 타입은 생략될 수 있다.

(동적타이핑)

 

package main

import "fmt"

var i, j = 1, 2

func main() {
	var c, python, java = true, false, "no!"
	fmt.Println(i, j, c, python, java)
}

 

-short variable declarations

 

함수 내부에서는 묵시적 타입 선언 var을 대체하여 :=  선언식을 사용할 수 있다.

하지만 함수 외부에서 모든 선언은 var func와 같은 키워드로 선언되기에 , := 은 유효하지 않다.

 

-basic types

 

bool

string

int  int8  int16  int32  int64
uint uint8 uint16 uint32 uint64 uintptr

byte // alias for uint8

rune // alias for int32
     // represents a Unicode code point

float32 float64

complex64 complex128

다음과 같은 기본 자료형이 있다. int, uint, uintpr은 32비트 시스템에선 32비트 64비트 시스템에선 64비트 가 된다.

근데 굳이 특정할 필요가 없다면 int사용해도 된다.

 

다른 자료형도 마찬가지.

 

-zero values

 

특정 초기값을 지정해주지 않으면 0으로 초기화된다.

  • 0 for numeric types,
  • false for the boolean type, and
  • "" (the empty string) for strings.

-type conversions(오버캐스팅)

var i int = 42
var f float64 = float64(i)
var u uint = uint(f)

 

타입을 바꾸기 위해서는 위와 같이 T(v)를 사용한다.

 

하지만 c와 여타 언어와는 다르게, 형변환 없이 다른 자료형의 값을 할당할 수 없다.

예를들어 var f float64 = float64(i)에서 f는 이미 float64자료형으로 선언 됐기 떄문에 f = i 이런식으로 초기화 할 수없다.

 

-type inference

j := 1

라거나 var i = 1 이런식으로 동적 타이핑 되는 것을 봤는데

var i int
j := i // j is an int

와 같이 이미 타입이 있는 변수로 초기화 되는 경우에는 우측 변수값으로 infer돼서 타입이 할당 된다.

 

우측 변수 값으로 타입화되지 않은 숫자 상수가 온다면 변수에 필요한 정밀도를 고려해 타이핑이 된다.

 

-constants

상수는 변수와 비슷하나, const 키워드로 선언된다.

문자,문자열,불리안,숫자형 모두 됨..

:= 구문 사용 불능

 

-numeric constants

숫자 상수는 고 정밀도 값이다.

타입되지 않은 상수는 그 문맥과 정황에 따라 타입화된다.

package main

import "fmt"

const (
	// Create a huge number by shifting a 1 bit left 100 places.
	// In other words, the binary number that is 1 followed by 100 zeroes.
	Big = 1 << 100
	// Shift it right again 99 places, so we end up with 1<<1, or 2.
	Small = Big >> 99
)

func needInt(x int) int { return x*10 + 1 }
func needFloat(x float64) float64 {
	return x * 0.1
}

func main() {
	fmt.Println(needInt(Small))
	fmt.Println(needFloat(Small))
	fmt.Println(needFloat(Big))
}

 

Exercise: Loops and Functions

 

package main

import (
	"fmt"
	"math"
)

func Sqrt(x float64) float64 {
	z := 1.0
	for i := 1 ; i <= 10; i++ {
		z -= (z*z - x) / (2*z)
		fmt.Printf(" z = %f ", z)
		
	}
	return z
}

func main() {
	fmt.Println(Sqrt(2))
	fmt.Println(math.Sqrt(2))
}

(z*z - x) 는 z제곱이 x 에서 얼마나 떨어졌느냐  (2*z)는 z^2의 미분값으로 즉 변화량/변화율 이라고 한다. 

z한단 위가 얼마나 변했느냐 .. z단위하나당 z^2 -x 가 어떻게 변화 했느냐를 의미한다. 이를 반복하면서 추정해나가는 것을 newton method라고 한다고 한다.

 

-switch

 

if else문 을 짧게 쓰는 하나의 방법.

 

case문마다 break를 입력하던 수고가 필요 없다고 한다.

또한 c언어나 java(1.7이전) 까지 case문의 조건으로 상수만이 올 수 있었는데, go는 굳이 상수가 아니라도 괜찮으며, 값들이 굳이 정수일 필요도 없다.

 

package main

import (
	"fmt"
	"runtime"
)

func main() {
	fmt.Print("Go runs on ")
	switch os := runtime.GOOS; os {
	case "darwin":
		fmt.Println("OS X.")
	case "linux":
		fmt.Println("Linux.")
	default:
		// freebsd, openbsd,
		// plan9, windows...
		fmt.Printf("%s.\n", os)
	}
}

에서 runtime.goos는 현재 의 os를 문자열로 반환한다.

-switch evaluation order

 

탑에서 바탐으로 순차적으로 케이스를 평가하기 때문에, 맞는 케이스를 만나면 아래는 실행하지 않는다.

package main

import (
	"fmt"
	"time"
)

func main() {
	fmt.Println("When's Saturday?")
	today := time.Now().Weekday()
	switch time.Saturday {
	case today + 0:
		fmt.Println("Today.")
	case today + 1:
		fmt.Println("Tomorrow.")
	case today + 2:
		fmt.Println("In two days.")
	default:
		fmt.Println("Too far away.")
	}
	fmt.Println(time.Now().Weekday())
}

에서 go web play ground 의 시간은 오픈시간인 2009 -11-10 23:00:00 UTC에 고정되어 잇기 떄문에 화요일에 머물러 있다고 한다

-switch with no condition

comprises 포함하다 구성되다

a comprises b a가 b를 포함하고 있다.

parenthesize 소괄호
parenthesized 소괄호로 감싸진

factored 요소로 분해된, 분리된.

implicit 암묵적인 함축적인 묵시적인

visible 보이는, 시각적으로 인식되는 , ( 그렇기떔에 유효한 이런 뜼으로도 쓰임)

댓글