니꼬쌤과 함께하는 Go언어!!

 

전에는 Bank예제로 struct를 살펴보았다

https://jejehoon.tistory.com/22

 

struct in Golang (수정)

Struct 이번에는 니꼬쌤이 설명해주신 struct라는 개념이 잘 이해되지 않아서 인터넷을 활용해 직접 찾아보았다 내가 생각하는 struct(아니라면 태클 부탁드립니다) : Go는 전통적인 객체지향 언어라고 불리는 파..

jejehoon.tistory.com

이번엔 Dictionary(사전) 예제로 struct를 쓰지 않고 type만 쓰는 것을 살펴보자

왜 struct를 쓰지 않을까?내 생각엔 필요한 요소는 단어와 정의뿐이라 그런 것 같다(물론 형태나 예문이 들어갈 수 있지만 기본적인 사전을 나타내고자 한 것 같다) 필요한 요소가 더 많다면 struct를 쓰는 게 더 효율적이나 그렇지 않다면 굳이 struct를 쓸 필요가 없다  

Type

먼저 mydict라는 폴더와 go파일을 만들고 package mydict해준다

타입을 정하는 type문에 struct가 아닌 map을 활용해서 Dictionary타입을 만들자 map은 키와 밸류로 2가지 요소가 들어간다 Dictionary에 딱 맞는 타입이다 map에 들어가는 요소는 단어와 정의 이므로 둘 다 string형태이다

package mydict

type (d Dictionary) map[string]string

사전의 기능은 무엇이 있을까? 1. 단어를 찾는다 2. 단어의 정의를 확인한다  이렇게 사전의 기능을 잘 활용하기 위해서는 단어가 필요하다 그렇다면 3. 단어를 추가하는 기능! 또 단어나 정의가 잘못되었다면 4. 삭제하는 기능! 여러 가지 기능들이 필요하다 물론 우리는 스크롤을 내려서 수많은 단어 중하나하나 단어를 찾고 확인하고 추가 또는 삭제할 수 있지만 힘들다 그래서 필요한 것은 바로 Method! 

Method

method는 struct의 것과 같고 일반 type문에서도 사용할 수 있다 단 receiver의 경우 reference type인지 아닌지에 따라  포인터를 사용하는지 안 하는지 나뉜다! 예를 들자면 struct에서는 *(포인터)를 안 쓴 경우 원래의 것이 그대로 복사되어 나타난다 하지만 map처럼 reference type은 값의 복사를 전제로 깔고 있어서 포인터를 사용하면 안 된다 

네 가지의 Method를 모두 작성해보자

package mydict

import "errors"

// Dictionary type
type Dictionary map[string]string

var (
	errNotFound   = errors.New("Not Found")
	errWordExists = errors.New("Word Exists")
	errCantUpdate = errors.New("Cant Update Non-existing Word")
	errCantDelete = errors.New("Cant Delete Non-existing 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, def string) error {
	_, err := d.Search(word)
	switch err {
	case nil:
		d[word] = def
	case errNotFound:
		return errCantUpdate
	}
	return nil
}

// Delete a word
func (d Dictionary) Delete(word string) error {
	_, err := d.Search(word)
	switch err {
	case nil:
		delete(d, word)
	case errNotFound:
		return errCantDelete
	}
	return nil
}

error는 struct와 동일하게 체크해주는 용도로 사용한다 Go는 거의 강제적으로 error를 체크해야 한다고 한다

  https://blog.golang.org/maps 여기서 map의 활용법에 대해서 알 수 있다 exist와 delete 같은 경우는 이 쪽을 참고하면 형태를 잘 파악할 수 있다

Search, Add, Update, Delete를 작성했는데 모두 단어가 없을 때의 error를 나타내 주었고 map type이기 때문에 *(포인터)를 쓰지 않았다 

그러나 각각에 들어가는 인자는 각 기능마다 다르다

Search 같은 경우는 정의가 아닌 단어를 찾기 때문에 word만

Add는 추가할 때 정의도 같이 추가해야 하기 때문에 word def 둘 다

Update는 정의를 바꾸는 것이기 때문에 def만 필요할 것 같으나 word로 찾아야 하기 때문에 둘 다 

Delete는 단어를 삭제하면 되기 때문에 word만(정의도 같이하려면 def)

이렇게 인자가 어떤 것이 들어가야 될지 생각해보고 정의하면 된다

 

 완성하기까지 중간중간 체크를 하면서 만들어야 한다

package main

import (
	"fmt"

	"github.com/pavk/learngo/mydict"
)

func main() {
	dictionary := mydict.Dictionary{"first": "First word"} //첫 단어
	baseword := "hello"
	definition := "Greeting"
	err := dictionary.Add(baseword, definition) //둘째 단어 추가
	if err != nil {
		fmt.Println(err) //추가 가능한지 확인
	}
	hello, _ := dictionary.Search(baseword)
	fmt.Println(hello) // 추가 되었는지 확인
	definition = "Bowing" 
	err2 := dictionary.Update(baseword, definition)//둘째 단어 업데이트
	if err2 != nil {
		fmt.Println(err2)//업데이트 가능한지 확인
	}
	word, _ := dictionary.Search(baseword)
	fmt.Println(word)// 업데이트 되었는지 확인
	err3 := dictionary.Delete(word, definition)//둘째 단어 삭제
	if err3 != nil {
		fmt.Println(err3)//삭제 가능한지 확인
	}
	check, _ := dictionary.Search(word)
	fmt.Println(check)//삭제 되엇는지 확인
}

결과는!!

 

추가되었고 업데이트되었고 삭제되었다

'노마드코더스 아카데미 > Go언어로 웹스크래퍼 만들기' 카테고리의 다른 글

struct in Golang (수정)  (0) 2020.03.17
Go웹스크래핑[3]  (0) 2020.03.13
Go웹스크래핑[2]  (0) 2020.03.12
Go웹스크래핑[1]  (0) 2020.03.11
Go 웹스크래핑[0]  (0) 2020.03.11

Struct

이번에는 니꼬쌤이 설명해주신 struct라는 개념이 잘 이해되지 않아서 인터넷을 활용해 직접 찾아보았다

 

 내가 생각하는 struct(아니라면 태클 부탁드립니다) : Go는 전통적인 객체지향 언어라고 불리는 파이썬, 자바, 자바스크립트, 씨플플 등이 가지고 있는 클래스, 객체, 상속과 같은 개념이 없는 언어 (싹수없다는 거 아님) 하지만 클래스의 역할을 하는 것이 바로 struct.   니꼬쌤은  struct는 object와 비슷하면서 map보다는 유연한 것이라고 하셨다 그럼 다른 언어들에서 클래스, 객체, 상속이 도대체 뭘까? 그걸 알면 struct도 알 수 있지 않을까? 해서 찾아본 결과 아!! 이게 말로만 듣던 붕어빵과 붕어빵 틀 아빠와 아들 이야기구나 했다 

 

 클래스와 객체를 설명하기 위해 사과를 예로 들자면 사과하면 떠오르는 물체가 있을 텐데 그것을 이상적인 형태의 사과라고 했을 때 실제로 먹는 사과는 떠오르는 사과와 완벽하게 일치하지는 않는다 하지만 우리는 그것을 사과라고 인식한다 여기서 사과하면 떠오르는 물체가 바로 클래스이고 실제로 먹는 사과들이 바로 객체(object)이다 붕어빵과 붕어빵 틀로는 붕어빵 틀이 클래스 실제로 먹는 붕어빵이 객체(object)인 것이다 붕어빵이 굽히는 과정상속받는다라고 말할 수 있다 찾다 보니 진짜 설명 잘하신 분이 있어서 https://youtu.be/vrhIxBWSJ04 공유한다

 

 struct가 클래스와 비슷한 역할을 한다면 이제는 좀 이해가 된다 형태를 보면 이해가 더 잘 될 것이다

person이라는 struct를 만들었다 

type person struct {
    name string
    age	 int
    favFood []string
}

func main() {
	favFood := []string{"spam","ramen"}
    pavk :=person{name:"pavk",
    			age:25,
                  	favFood:favFood} (map이었다면 key와 value값이 각각 일정한 형태였을 것이다 )
   	fmt.Println(pavk.name)
}

//결과--> pavk

객체지향 언어로 봤을 때 person이라는 클래스와 pavk라는 객체(object)를 만든 것과 같다

 

일단은 지금과 같이 올리고 추후에 피드백과 더 많은 정보들을 찾아서 업데이트하도록 하겠다

 

(2020/03/16 수정)

Struct의 private과 public

 저번 package에서 알 수 있듯이 가져오기(import)한 패키지 중 보이는 것도 있고 아닌 것도 있다는 것을 우리는 알고 있다 대문자와 소문자로 그것을 구분하는데 대문자인 경우에는 public(보이는 것, 공용), 소문자인 경우에는 private(보이지 않는 것, 개인)이다 마찬가지로 struct, object도 이것이 포함된다 

 

 니꼬쌤은 은행계좌를 예로 들어주셨다

니꼬쌤이 하고자 하신 것은 1. 계좌 만들기 2. 다른 사람들이 함부로 쓸 수 없도록 만들기 3. 입출금 하기 및 잔액조회이다

 

 우선 struct자체를 컴파일할 것이 아니기 때문에 main함수는 만들지 아니한다

accounts라는 폴더와 accounts.go라는 파일을 만들어준 후 struct를 만든다 단 이폴더는 앞서 만들었던 learngo폴더 안에 만들어야 한다 왜냐하면 다른 폴더에 있으면 가져오기(import)가 되지 않는다

 

 위에서 보면 알 수 있다시피 type문을 활용해 struct를 생성해주고 객체(object), 객체 유형을 적어준다 

package accounts

type account struct {
	owner   string
	balance int
}

 main.go에서 코드를 작성해보면 알겠지만 account도 owner도 balance도 나타나지 않는다 private이기 때문이다 

그렇다고 대문자로 바꾸어서 public으로 만들어 버리면 다른 사람들이 함부로 쓸 수 있게 된다 그럼 private이면서 계좌를 생성할 수 있는 방법은?? 바로 함수와 포인터를 사용하는 것이다 

 

 NewAccount라는 함수를 만들어 account값을 반환해보도록 하자

package accounts

type Account struct {
	owner   string
	balance int
}

func NewAccount(owner string) *Account { //함수명이 대문자인 이유: public, main.go에서 호출하기 위해서!
	account := Account{owner: owner, balance: 0}
	return &account 
}

 위 코드에서 볼 수 있듯 함수의 반환하는 타입은 씨쓰루(*) 반환 값은 주소 값(&)이다 포인터를 사용한 이유는 만약 복사를 했다면 똑같이 private으로 나와서 사용할 수 없다 하지만 포인터형으로 반환을 한다면 결과는 이렇게 잘 나오게 된다

Struct와 Method

 앞서 private과 public을 계좌 만드는 것을 통해 알아봤다면 이번에는 Method를 입출금 및 잔액조회를 통해 알아보려고 한다 method는 간단하게 말하자면 기능이다 struct안에서 쓸 수 있는 기능이라고 생각하면 된다 함수와 정말 비슷하게 생겼다 다만 receiver라는 인자를 함수명과 func사이에 적어줘야 한다 receiver의 유형에는 Account가 들어간다 아마도 이 struct와 연결된 method라는 것을 인지 하기 위해 이렇게 하는 것이 아닐까 한다 한 가지! receiver에 들어가는 인자는 아무 이름이나 적어도 되지만 struct의 첫 글자의 소문자를 따와서 적는 것을 원칙으로 한다

 

 입출금과 잔액조회 method를 만들어준다

func (a/*인자이름*/ Account/*인자 유형*/) Deposit(amount int) {//입급 +
	a.balance += amount
}

func (a Account) Balance() int { //잔액조회용
	return a.balance
}
func (a Account) Withdraw(amount int) { //출금 -
	a.balance -= amount
}

 

 그다음 main.go에서 실행을 해주면?? 값이 0이 되어있다 그 이유는 receiver에 struct Account를 복사한 것이기 때문이다 그냥 복사해왔기 때문에 원래 값을 가지게 된다 그럼 여기서 필요한 것은?? 

포인터이다!! Account 앞에 *를 붙여줘서 씨쓰루 해주고 다시 실행해보면

잘 된 것을 볼 수 있다 

 

 그런데 계좌에서 마이너스는  허용되지 않는 다 잔액부족이라고 에러가 뜨지 그래서 니꼬쌤은 에러를 만들기로 했다 

출금할 때 출금할 돈이 잔액보다 많으면 에러가 뜨므로 if문을 통해 이렇게 만들어 준다 

func (a *Account) Withdraw(amount int) error {//반환 유형은 error
	if a.balance < amount {
		return errors.New("Can't withdraw")
	}
	a.balance -= amount
	return nil //파이썬이나 자바스크립트의 none,null처럼 아무것도 없는 것을 반환한다 
    //error도 두가지 유형이 있는데 에러가 난경우 error 아닌경우 nil
}
func main() {
	account := accounts.NewAccount("pavk")
	account.Deposit(10)
	err := account.Withdraw(20)
	if err != nil {//error가 nil이 아닌경우 즉 에러가 난경우!
		log.Fatalln(err)
	}
	fmt.Println(account.Balance())

}

컴파일을 해보면

이런 결과가 나온다 

 

※Go는 에러가 날 만한 것들을 하나하나 이런 식으로 체크해주어야 한다 너무 많으면 변수로 깔끔하게 정리할 수 있다

 

마지막으로 깔끔하게 출력을 해보자

 

잔액조회를 위해선 계좌 주인의 이름과 잔액을 나란히 써주면 된다 

 

pavk's account : 10$ 이런식으로 말이다

 

Python에서는 클래스를 출력하면 클래스가 가진 매서드를 string형태로 출력한다 

 

마찬가지로 Go도 struct를 프린트하면 매서드를 string형태로 출력할 수 있는데 그 방법이 바로 String( ) 매서드이다

 

//Owner매서드가 없기 때문에 만들어준다

func (a Account) Owner() string {

    return a.owner

}

//String 매서드

func (a Account) String() string {

    return fmt.Sprint(a.Owner(), "'s account : ", a.Balance(), "$")

}

이렇게 String매서드를 작성해주고 (여기서 receiver인자에 *가 안 들어가는 이유는 변화하는 값이 없기 때문이다 private 하게 지켜줘야 한다는 뜻) main.go에서 account(struct)를 출력해주면 끝

이런 식으로 결과가 나온다!

'노마드코더스 아카데미 > Go언어로 웹스크래퍼 만들기' 카테고리의 다른 글

Dictionary use type in Go lang (feat. map)  (2) 2020.03.24
Go웹스크래핑[3]  (0) 2020.03.13
Go웹스크래핑[2]  (0) 2020.03.12
Go웹스크래핑[1]  (0) 2020.03.11
Go 웹스크래핑[0]  (0) 2020.03.11

1. 포인터

Low level programming language :  C언어와 같이 컴퓨터가 쉽게 이해하도록 프로그래밍하는 것. 실행 속도가 빠르지만 배우기 어렵다 유지보수가 힘들다 이런 언어들은 메모리 파트에 접근할 수 있다 그것이 바로 포인터!

 

예시1)

a=2

b=a        일 때 b는 a의 값을 복사해서 가져온다

a=10       후에 b와는 상관없이 a값에 10을 가져오면 a는 10이 된다

a와 b의 값은 각각 10,2

 

& : &뒤에 나오는 값이 가지는 메모리 주소를 알려주는 기능이다

예시2)

a=2

b=&a      b는 a의 주소 값을 가져온다

a=10       

a와 b의 값은 각각 10, a의 주소 값

 

* : *뒤에 나오는 주소가 가지는 값을 알려주는 기능이다 (씨쓰루)

예시 3)

a=2

b=&a

*b의 값은 2

*b=5일 때

a의 값은 얼마일까?

*b로도 a값을 바꿀 수 있기 때문에 답은 5이다

 

이렇게 포인터를 알아보았는데 포인터는 컴퓨터에서 복사가 아닌 바로가기의 느낌이다

 

복사는 용량 전체를 가져오지만 바로가기는 연결만 할 뿐 내용 전체를 담아오지는 않는다

 

두 개의 변수가 하나의 object로 서로 연결되어있기 때문에 빠르게 대응할 수 있다

b = a, a = 2 b = &a, a = 2
&a = a주소값

&b = b주소 값

&a = a주소값 &b = b주소값
a = a b = a a = a b = &a
*(&a) = 2 *(&b) = 2 *(&a) = 2 *(&b)! = 2
    *a = error *b = 2

b=&a인 경우에도 &b=b의 주소 값을 가진다 하지만 *(&b)는 2가 아니고 &a이다

2. Arrays and Slices

Array : Go에서 Array(배열)은 요소의 개수와 형태를 입력해주어야한다

 

ex)

  names := [5] string{"nico","lynn","dal","pavk"} //요소개수를 정했다면 그보다 많이 적을 수는 없다

  names[4]="hui"  //요소를 추가하는 방법

  names[5]="asd" //6번째 이름을 추가하는 것이므로 에러가 난다 

 

Slices : 하지만!! Slices는 제한이 없는 배열이다 융통성있는 배열

 

ex)

  names := [ ] string{"nico","lynn","dal","pavk"} //요소개수를 비움으로서 요소개수제한이 없다

  names = append(names, "hui") //slice에 요소를 추가하는 방법

※append는 slice를 수정해서 요소를 추가하는 것이 아닌 요소가 추가된 새로운 slice를 반환한다

  

3. Map

map : 파이썬의 dictionary와 비슷한 형태이다 key와 value형태를 가지고 있다

 

ex)

  pavk :=map[string]string{"name":"pavk","age":"25"}

//key와 value 형태를 string으로 지정했으면 숫자여도 "25"이렇게 써줘야한다

 

ex)map을 활용한 반복문

  pavk :=map[string]string{"name":"pavk","age":"25"}

  for key,value := range pavk{ //배웠던 반복문 처럼 쓰면 되는데 배열과 다르게 index를 반환하지않고 key를 반환한다

       반복할 내용

  }  

 

 

1. for 반복(loop) 문

go에서는 for문만을 사용한다

 

forEach나 for in 같은 경우는 사용할 필요가 없다고 한다

 

왜냐하면 range를 사용할 것이기 때문이다 

(1) range

range란? 각각의 배열 요소에 반복할 내용을 실행시킨다

 

형태 : for 변수 := range 범위가 될 어떤 것(배열, 슬라이스, 문자열){

                  반복할 내용

         }

 

예시) superAdd함수에 들어있는 인자(2,3,4,5,7,9)의 개수 6개만큼 numbers를 출력한다  ≒forEach( ) in javascript

func superAdd(numbers ...int) int{
	for number := range numbers{ //반복할 횟수는 numbers의 개수
		fmt.Println(number)	 //반복될 내용
    }
	return 1
}

func main(){
	superAdd(2,3,4,5,7,9)       //numbers의 개수는 6개
}

실행결과를 보면 

이렇게 나오게 되는데 배열 요소의 개수만큼 자동으로 index값을 받게 되어서라고 한다

array(배열)과 slice(슬라이스: 융통성 있는 배열?)에서 range반복문은 index값과 배열 안의 값을 생성한다(index먼저 생성)

 

index를 보기 싫다면 for의 변수 중 처음은 무시하고( _ 언더바 사용 ) 두 번째 것을 입력하면 된다

이렇게

func superAdd(numbers ...int) int{
	for _,number := range numbers{ 
		fmt.Println(number)	 
    }
	return 1
}

func main(){
	superAdd(2,3,4,5,7,9)       

(2) i 사용

C언어와 비슷하다

꼭 i만 써야 되는 것은 아니다(하지만 아마도 수는 안될 것이다)

형태: for i:=0; i <범위(대신 수 형태여야 함); i++{

            반복할 내용

       }

(3) 총합 구하기 예제

package main

import (
	"fmt"
)

func superAdd(numbers ...int) int {
	total := 0                   	//총합이 되어줄 친구 반복문 밖에 있어야함
	for _, number := range numbers {//index는 보기싫어서 _로 무시
		total = number + total		//total변수에 각각의 수를 더해주기
	}
	return total
}

func main() {
	result := superAdd(2, 3, 6, 7, 9, 10)
	fmt.Println(result)
}

//결과 37

요약

1. for만 사용(for in, forEach 없음)

2.range는 배열에선 index값을 먼저 생성한다

3.i 같은 변수로도 범위를 구할 수 있다

 

2. if ~ else, switch~case

1. if ~ else

1) 다른 언어들과 다르게 ( )이나 :이 필요 없다

2) VScode에서 제공하는 extention return값을 주면 else를 쓸 필요 없다

3) if문을 쓰는 도중에 변수를 생성할 수 있다(무엇을 위한 변수인지 알아보기 쉬움) 

	if koreanAge := age + 2; koreanAge < 18 { //(),:필요없이 조건 바로적음 //koreanAge := age + 2; if문을 쓰는 도중에 변수만들기
		return false
	} 
	return true //else{ return true} 였을텐데 return true만 적어도 실행가능 
	

else if 조건을 추가할 때 쓰임

if 조건{

 

} else if 조건{

 

} else {

 

}

2. switch/case

1) C나 javascript와 많이 비슷하다(파이썬은 switch를 사용하지 않음)

2) if~else와 마찬가지로 쓰는 도중에 변수를 생성할 수 있다

3) else if를 도배할 필요 없이 case로 짧게 짧게 쓸 수 있다

 

package main

import (
	"fmt"
)

func canIdrink(age int) bool {
	switch koreanAge= age+2; koreanAge { //switch문 도중 변수 선언 가능
	case age < 18:			//만약 if문을 썼다면 else if로 도배될 것을 case로 짧게 짧게
		return false
	case age ==18:
		return true
	}
	return false
}

func main() {
	result := canIdrink(18)
	fmt.Println(result)
}

 

1. main Package

패키지란?

Go언어가 코드의 모듈화, 코드의 재사용과 같은 기능을 제공하기위해 사용하는 것이다

 

이전에 만든main.go는 패키지라고 불리고 앞서 말했듯 컴파일러에게 특별하게 인식된다

 

컴파일러는 main.exe(실행파일)을 만든다

 

Go에서는 main package를 쓰고 있다는 것을 작성해주어야한다

또 main package는 main 함수를 필요로한다 Go 프로그램의 시작점이 되는 부분이기 때문이다(C의 느낌이 강하게 난다)

package main

func main() {
} 

프로그램을 실행시키는 방법도 특이하다 터미널(명령 프롬프트)에 파일 저장 후 go run main.go라 입력해야 한다

 

2. fmt Package and Import

fmt는 formatting을 위한 패키지이다 이때 중요한 것은 함수 첫 글자는 항상 대문자로 써야한다는 점이다

그렇지 않을경우 나타나지지 않는다

 

첫글자가 소문자일경우는 private한 함수이고 대문자일 경우는 export된 함수이기 때문이다(이건 Go에서 지정한 약속같다)

package main

import "fmt"

func main() {
fmt.Println("Hello world!") //Println의 P가 대문자이다 export!
}

※컨트롤키를 누른채 fmt를 클릭하게된다면 fmt 안의 내용을 알 수 있다  또 fmt를 사용하지 않게 되면 자동으로 import문이 사라진다 (VScode의 장점)

3. function(함수)

변수와 상수 variable(=var), constant(=const) 각각 '변할수 있음'과 '변할수 없음'

 

Go에서 변수를 선언하기위해서는 type도 알려주어야한다 ex) var name string = "pavk"

 

함수 안에서는 이것을 축약형으로 name :="pavk"라고 쓸 수 있다(type은 Go가 알아서 찾아준다고 한다ㅎㅎ)  

name := "nico" //축약형
var name string = "lynn" //원래(너무 김)

 

또한 Go는 만들어 놓고 쓰지 않는 것을 굉장히 싫어한다 쓰지않으면 에러를 발생시킨다

 

 

Go는 함수에서 반환값을 2개 이상 가질 수 있다 (<--이것이 아마 병행성의 이유이지 않을까?)

또한 println처럼 인자를 무제한으로 가지려면 ...type을 써주면  된다

func lenAndUpper(name string) (int, string) {
	return len(name), strings.ToUpper(name) //2개의 반환값을 반환함!!
}

func repeatMe(words ...string) { //'...'만 있다면 무제한 인자!!
	fmt.Println(words)
}

func main() {
	repeatMe("nico","lynn","dal","marl","flynn","pavk")//이렇게 많은 인자도 출력이 가능하다
}

naked return : 반환값을 return 뒤가 아니라 반환값의 type 앞에 적을 수 있다

defer : 반환을 한 후에 추가로 실행을 시킬 수 있다  

func lenAndUpper(name string) (lenght int, uppercase string) { //여기 type들 앞에서 변수처럼 만들어지고 반환값으로도 사용된다
	defer fmt.Println("I'm done") //반환하고 추가로 I'm done을 출력함
	lenght = len(name)
	uppercase = strings.ToUpper(name)
	return			//여기가 아니라
}

defer를 화인해보기위해서 출력을 해보았다

package main

import (
	"fmt"
	"strings"
)

func lenAndUpper(name string) (length int, uppercase string) {
	defer fmt.Println("I'm done")//2.두번째로 실행되어야한다
	length = len(name)
	uppercase = strings.ToUpper(name)
	fmt.Println(length, uppercase)  //1.먼저 실행되어야 defer가 실행되는것을 알 수 있다
	return
}

func main() {
	totalLength, up := lenAndUpper("nico")
	fmt.Println(totalLength, up)//3.세번째
}

 

실행결과!

 

예전부터 Go언어를 접해보고 싶었지만 영어 때문에 안 배우고 있었는데

 

슬랙에 올라온 한국어 패치가 되었다는 내용을 보자마자 달려갔다(올라온지는 꽤 됐었고 어제 봤음)

https://nomadcoders.now.sh <--노마드코더 슬랙

 

그래서 Go란 무엇이냐?

Go는 2009년 구글이 개발한 프로그래밍 언어로 가비지 컬렉션 기능이 있고, 병행성을 잘 지원하는 컴파일 언어라고 한다

 

(1) 가비지 컬렉션(쓰레기 수집?)? ==> 메모리 관리 기법 중의 하나로, 프로그램이 동적으로 할당했던 메모리 영역 중에서 필요 없게 된 영역을 해제하는 기능이다.

 

(2) 병행성? ==> 컴퓨터 과학에서 여러 계산을 동시에 수행하는 시스템의 특성으로, 잠재적으로는 서로 상호 작용이 가능하다. 이와 상대적인 개념으로는 병렬성이 있다

 

(1)(2)를 합치면? 실행 속도가 빠르다!! 

 

니꼬쌤도 빠르다는 것을 빨리 보여주고 싶어서 앞서 우리가 했던 파이썬 스크래핑과 Go스크래핑을 비교하며 보여줬다

 

온라인 세팅은 파이썬 때와 마찬가지로 Repl.it을 사용할 수 있다

 

하지만 나는 니꼬쌤이 추천한 VScode(Visual Studio Code)와 Go를 설치하고 실행했다(오프라인)

VScode는 에디터 Go는 프로그래밍 언어이다

https://code.visualstudio.com/Download <--VScode는 여기서 윈도우, 맥, 리눅스 등 다양한 버전에 맞게 설치를 한다

https://golang.org/dl/<--Go는 여기서  윈도우, 맥, 리눅스 등 다양한 버전에 맞게 설치를 한다

 

Go를 설치할 때 주의할 점은 로컬 드라이브에 go폴더와 bin폴더를 만들어 주어야 한다 ex) C:\go\bin

 

go폴더는 GOPATH환경을 위해 꼭 필요하다고 한다 (자세한 내용은 Go를 다운로드하는 버튼을 클릭하면 나옴 영어로)

 

main.go는 go폴더 안의 src폴더 안의 github.com안의 자신의 닉네임 폴더 안의 learngo폴더에 저장해주면 좋다

ex) C:\go\src\github.com\pavk\learngo\main.go(없으면 생성해야 함)

 

main.go는 컴파일하기 위해서 꼭 필요한 패키지이다

 

공유, 오픈소스코드를 만들기 위함이라면 main.go를 만들면 안된다

 

나는 window10 사용자여서  VScode를 실행하여 새 파일을 생성고 저장을 통해 이름과 확장자를 main.go로 바꾸었다

 

그러면 VScode에서 Go를 사용하기 위해 업데이트를 하라고 막막막 뜨는데 그것을 다 하자는 대로 해주면 된다

 

이런 화면이 나왔다면 성공! 기본적인 세팅은 끝났다

 

+ Recent posts