➤ projectdiscovery➤ Remix➤ Rescript➤ Purescript➤ npm➤ Cloudflare➤ React➤ Next.js➤ GO➤ Hyper-V➤ Tibero➤ Git➤ Algorithms, 2020년
Note.nomadcoders-go-for-beginners
May 1, 2021Go 설치하기
- Golang.org 접속
- Download Go 에서 OS에 맞는 설치파일 실행
Go PATH 디렉토리에서만 GO 프로젝트 생성 및 실행 가능
- 윈도우 : C:\go
- 맥 : /(local)user/go
Packages and Imports
-
패키지명이
main
인 경우 실행 프로그램으로 인식 및 Entry Point -
패키지를 불러올 때
import
-
export
할 함수명의 첫글자는대문자
func sayA(){ // export 불가능
fmt.Println("A")
}
func SayB(){ //export 가능
fmt.Println("B")
}
Variables and Constants
-
선언할 때
type
지정 필요 -
상수(Constant) : 값 변경 x
const name string = "golang"
- 변수(Variables) : 값 변경 o
- 축약형(타입 추론) 선언 가능
:=
- func 안에서만 선언 가능
- 축약형(타입 추론) 선언 가능
const name string = "golang"
name = "go"
age := 25
Functions
- 파라미터와 반환값의
type
명시 필요
func multiply(a, b int) int {
return a * b
}
- 여러 개의
반환값
을 가질 수 있음
totalLen, upperName := lenAndUpper("go")
fmt.Println(totalLen, upperName) // OUTPUT : 2 GO
fmt.Println(lenAndUpper("golang")) // OUTPUT : 6 GOLANG
totalLen, _ := lenAndUpper("go") // 반환값 무시
- 가변인자함수 Variadic Function
- 3개의 마침표 사용
...
- 가변 파라미터 전달 가능
- 3개의 마침표 사용
func print(name ...string) {
fmt.Println(name)
}
func main() {
print("a", "b", "c", "d", "e")
// OUTPUT : [a b c d e]
}
Named Return Parameter
들에 리턴값들을 할당하여 리턴
func sum(nums ...int) (count int, total int) {
for _, n := range nums {
total += n
}
count = len(nums)
return
}
func main() {
fmt.Println(sum(1, 2, 3)) //OUTPUT : 3 6
}
defer
- 함수가 끝나고 나서 실행
func sum(nums ...int) {
defer fmt.Println("I'm done!")
total := 0
for _, n := range nums {
total += n
}
count := len(nums)
fmt.Println(count, total)
}
func main() {
sum(1, 2, 3)
}
//OUTPUT
3 6
I'm done!
IF
- if 조건식
if a>10 {}
- 조건식에
변수 선언
가능
func canIDrink(age int) bool {
if kage := age + 2; kage < 18 {
return false
}
return true
}
func main() {
fmt.Println(canIDrink(18)) //OUTPUT : true
}
SWITCH
- case에 조건문 가능
func canIDrink(age int) bool {
switch {
case age < 18:
return false
case age >= 19:
return true
}
return false
}
func main() {
fmt.Println(canIDrink(18)) //OUTPUT : false
}
Pointer
- 주소
&
- 포인터
*
func main() {
a := 2
b := a
a += 1
fmt.Println(a, b) //OUTPUT : 3 2
aa := 3
bb := &aa
aa += 2
fmt.Println(aa, *bb) //OUTPUT : 5 5
*bb += 2
fmt.Println(aa, *bb) //OUTPUT : 7 7
}
Array
- 길이를 정해야함
func main() {
names := [5]string{"a", "b", "c"}
fmt.Println(names) // OUTPUT : [a b c ]
names[3] = "d" // OUTPUT : [a b c d ]
fmt.Println(names)
}
Slice
- 길이 가변적
- 요소를 추가할 때는
append
func main() {
names := []string{"a", "b", "c"}
fmt.Println(names) // OUTPUT : [a b c]
names = append(names, "d")
fmt.Println(names) // OUTPUT : [a b c d]
}
Maps
- key:value 형태
- type이 고정
func main() {
me := map[string]string{"name": "a", "age": "25"}
fmt.Println(me) //OUTPUT : map[age:25 name:a]
for key, val := range me {
fmt.Print(key, val) // OUTPUT : nameaage25
}
}
Struct
- 구조체
type person struct {
name string
age int
favFood []string
}
func main() {
meFood := []string{"candy", "jelly"}
me := person{"a", 25, meFood}
fmt.Println(me) //OUTPUT : {a 25 [candy jelly]}
you := person{name: "b", age: 20, favFood: meFood}
fmt.Println(you) //OUTPUT : {b 20 [candy jelly]}
}
private & public
- 앞문자가
소문자
일 경우private
banking.go
type Account struct{
owner string
balance int
}
main.go
func main() {
account := banking.Account{owner: "a", balance: 1000} // Error!
}
- 앞문자가
대문자
일 경우public
banking.go
type Account struct{
Owner string
Balance int
}
main.go
func main() {
account := banking.Account{Owner: "a", Balance: 1000}
fmt.Println(account) //OUTPUT : {a 1000}
}
construct
- 생성자는 없으나 생성자처럼 초기화 함수를 만들 수 있음
accounts.go
package accounts
// Account struct
type Account struct {
owner string
balance int
}
// NewAccount creates Account
func NewAccount(owner string) *Account {
account := Account{owner: owner, balance: 0}
return &account
}
main.go
func main() {
account := accounts.NewAccount("a")
fmt.Println(account) //OUTPUT : &{a 0}
}
Methods
func (매개변수이름 구조체이름) 메소드이름() 반환형 {
매개변수이름
은receiver
라고 한다.
accounts.go
// NewAccount creates Account
func NewAccount(owner string) *Account {
account := Account{owner: owner, balance: 0}
return &account
}
// Deposit x amount on your account
func (a *Account) Deposit(amount int) {
a.balance += amount
}
main.go
func main() {
account := accounts.NewAccount("a")
fmt.Println(account) //OUTPUT : &{a 0}
account.Deposit(10)
fmt.Println(account) //OUTPUT : &{a 10}
}
포인터 리시버
를 사용해야 실제 오브젝트에 반영
accounts.go
// NewAccount creates Account
func NewAccount(owner string) *Account {
account := Account{owner: owner, balance: 0}
return &account
}
// Deposit x amount on your account
func (a *Account) Deposit(amount int) {
a.balance += amount
}
// Withdraw x amount from your account
func (a Account) Withdraw(amount int) {
a.balance -= amount
}
main.go
func main() {
account := accounts.NewAccount("a")
fmt.Println(account) //OUTPUT : &{a 0}
account.Deposit(10)
fmt.Println(account) //OUTPUT : &{a 10}
account.Withdraw(5)
fmt.Println(account) //OUTPUT : &{a 10}
}
Error
- try catch나 exception 없음
error
를 직접 체크하고 return해야함- exception이 없기때문에
error
를 다룰 코드를 작성해줘야함
accounts.go
// Withdraw x amount from your account
func (a *Account) Withdraw(amount int) error {
if a.balance < amount {
return errors.New("Can't withdraw")
}
a.balance -= amount
return nil
}
main.go
func main() {
account := accounts.NewAccount("a")
fmt.Println(account) //OUTPUT : &{a 0}
account.Deposit(10)
fmt.Println(account) //OUTPUT : &{a 10}
account.Withdraw(15)
fmt.Println(account) //OUTPUT : &{a 10} *Not print error!!
}
main.go
func main() {
account := accounts.NewAccount("a")
fmt.Println(account) //OUTPUT : &{a 0}
account.Deposit(10)
fmt.Println(account) //OUTPUT : &{a 10}
err := account.Withdraw(15)
if err != nil {
fmt.Println(err) // OUTPUT : Can't withdraw
}
fmt.Println(account) //OUTPUT : &{a 10}
}
Map
- 값 존재 여부 확인 :
val, exists := dict[]
main.go
func main() {
dictionary := mydict.Dictionary{}
dictionary["one"] = "1"
definition, err := dictionary.Search("two")
if err != nil {
fmt.Println(err) // OUTPUT : Not Found
} else {
fmt.Println(definition)
}
}
mydict.go
// Dictionary type
type Dictionary map[string]string
var errNotFound = errors.New("Not Found")
// Search for a word
func (d Dictionary) Search(word string) (string, error) {
value, exists := d[word]
if exists {
return value, nil
}
return "", errNotFound
}
- 값 추가
mydict.go
var errNotFound = errors.New("Not Found")
var errWordExists = errors.New("That word already exists")
// Search for a word
func (d Dictionary) Search(word string) (string, error) {
value, exists := d[word]
if exists {
return value, nil
}
return "", errNotFound
}
// Add a word to the dictionary
func (d Dictionary) Add(word, def string) error {
_, err := d.Search(word)
switch err {
case errNotFound:
d[word] = def
case nil:
return errWordExists
}
return nil
}
main.go
func main() {
dictionary := mydict.Dictionary{}
err := dictionary.Add("one", "1")
if err != nil {
fmt.Println(err)
}
definition, _ := dictionary.Search("one")
fmt.Println(definition) //OUTPUT : 1
err2 := dictionary.Add("one", "1")
if err2 != nil {
fmt.Println(err2) //OUTPUT : That word already exists
}
}
- 값 수정
mydict.go
// Dictionary type
type Dictionary map[string]string
var (
errNotFound = errors.New("Not Found")
errWordExists = errors.New("That word already exists")
errCantUpdate = errors.New("Can't update non-exists word")
)
// Search for a word
func (d Dictionary) Search(word string) (string, error) {
value, exists := d[word]
if exists {
return value, nil
}
return "", errNotFound
}
// Add a word to the dictionary
func (d Dictionary) Add(word, def string) error {
_, err := d.Search(word)
switch err {
case errNotFound:
d[word] = def
case nil:
return errWordExists
}
return nil
}
// Update a word
func (d Dictionary) Update(word, definition string) error {
_, err := d.Search(word)
switch err {
case nil:
d[word] = definition
case errNotFound:
return errCantUpdate
}
return nil
}
main.go
func main() {
dictionary := mydict.Dictionary{}
baseWord := "hello"
dictionary.Add(baseWord, "hi")
err := dictionary.Update(baseWord, "yay")
if err != nil {
fmt.Println(err)
}
word, _ := dictionary.Search(baseWord)
fmt.Println(word) //OUTPUT : yay
}
- 삭제
delete(dictionary,word)
net/http
- URL 요청보내기
- HTTP.Get(url)
main.go
func main() {
urls := []string{
"https://www.airbnb.com/",
"https://www.google.com/",
"https://www.amazon.com/",
"https://www.reddit.com/",
"https://google.com/",
"https://soundcloud.com",
}
var results = make(map[string]string)
for _, url := range urls {
result := "OK"
err := hitURL(url)
if err != nil {
result = "FAILED"
}
results[url] = result
}
for url, result := range results {
fmt.Println(url, result)
}
}
var errRequestFailed = errors.New("Request Failed")
func hitURL(url string) error {
res, err := http.Get(url)
if err != nil || res.StatusCode >= 400 {
fmt.Println(res.StatusCode)
return errRequestFailed
}
return nil
}
Goroutines
- 여러 함수를 동시에(Concurrently) 실행할 수 있는 논리적 가상 스레드
- 앞에
go
를 붙여서 실행 - 메인 함수가 돌아가는 중에만 실행됨
func main() {
go sexyCount("a")
sexyCount("b")
}
func sexyCount(person string) {
for i := 0; i < 10; i++ {
fmt.Println(person, "is sexy", i)
time.Sleep(time.Second)
}
}
// OUTPUT
b is sexy 0
a is sexy 0
a is sexy 1
b is sexy 1
b is sexy 2
a is sexy 2
...
Channels
- goroutine과 메인함수 사이에 정보를 전달하기 위한 방법
- goroutine 사이에서도 가능
- 메시지를 받을 때까지 메인 함수가 기다림(blocking operator)
func main() {
c := make(chan bool)
people := [2]string{"a", "b"}
for _, person := range people {
go isSexy(person, c)
}
fmt.Println(<-c) // true
fmt.Println(<-c) // true
fmt.Println(<-c) // error
}
func isSexy(person string, c chan bool) {
time.Sleep(time.Second * 5)
c <- true
}
func main() {
c := make(chan string)
people := [2]string{"a", "b"}
for _, person := range people {
go isSexy(person, c)
}
for i := 0; i < len(people); i++ {
fmt.Println(<-c)
}
}
func isSexy(person string, c chan string) {
c <- person + " is sexy"
}