본문 바로가기
  • hazard_dev@__
  • hazard_dev@__
Go

[Go#2] Go언어 변수_ 상수, 타입, 타입 캐스팅!!!

by Hazard3_o00sung 2021. 1. 3.
728x90

구글의 강력한 오픈소스 언어 Go언어입니다

 

Powerful Concurrency Language Go

  저번 시간에는 고 설치법 및 기본적인 사용방법에 대해서 알려드렸습니다. 만약 설치를 못하신 분이라면 아래 링크를 통해 설치를 하고 오시는 것을 추천드립니다!! 

hazarddev.tistory.com/63

 

[Go#1] Go언어 설치 및 기본 사용방법!!!

Installing Go _Each Os And Introduce 다양한 언어에 대한 소개를 작성하고자 하는데, 그중 요새 매우 핫한 Go프로그래밍 언어에 대해서 소개를 진행하고자 합니다!! 우선 Go 언어는 오픈소스 프로젝트 언

hazarddev.tistory.com

이번 시간에 설명드릴 내용은 고의 변수 타입 및 상수, 형 변환에 대해서 알려드리려 합니다!! 물론 쉽지 않지만 천천히 따라오시다 보면 금방 따라오실 수 있을리라 생각합니다! 변수의 개념은 어떻게 되는지 다들 아시겠지만 간략하게 짚고 넘어가도록 하겠습니다!

 

(lvalue) := (:rvalue)

 

현재 대부분의 프로그래밍 언어는 위와 같이 좌변값에 우변 값을 대입하는 방식으로 변수를 초기화합니다. 물론 변수를 이와 같이 선언만 해줄 수 있겠죠?

 

(lvalue);

 

하지만 프로그래밍만 하는 개발자레벨에선 보이진 않지만 실제로 하드웨어 레벨에서는 이러한 변수 선언이 있을 시, 메모리 주소 값을 사상시키기 때문에 값이 아예 없는 것은 아닙니다. 그러한 예는 아래를 보면 확실히 알 수 있죠.

 

#include <stdio.h>

int main()
{
	int a;
	printf("%d\n", a);
	return 0;
}

 

위와 같은 값이 존재할 때, %p를 이용한 출력을 하던 대응되는 값이 출력됨을 알 수 있습니다. 위 언어는 C언어를 이용해 작성이 되었으며, 변수에 대한 설명을 간략히 드리고자 추가했으니 무시해도 됩니다. 그냥 이렇게 된다라는 겁니다. 그렇다면 Go언어에서는 변수가 어떻게 선언되는지 알아봅시다!

 

var (variable_Name) (variable_Type) = (initial_Value)
var (variable_Name) (variable_Type) -> declare

 

위와 같은 구조를 지닙니다! 변수 이름, 타입, 초깃값이 존재할 때는 바로 초기화를 진행해서 동시에 선언해주면 되지만 그냥 선언할 때는 2번째줄과 같이 선언을 진행합니다.

 

package main

import "fmt"

func main() {
	var i int
	var j int = 10;
	fmt.Println(i, j)
}

 

이렇게 작성된 코드는 우리가 처음 작성했던 소스 코드를 삭제해주시고 작성하시면 됩니다. 결과는 당연히 아래와 같이 출력되게 됩니다.

$ 0, 10

 

,는 오타지만 여하튼 위와 같은 값이 출력되게 됩니다. 그리고 고 같은 경우엔 다양한 방식으로 변수 초기화를 지원합니다. 그러니까 다중 선언도 지원하지만 만약 초깃값이 존재할 경우에는 형선언을 해주지 않아도 컴파일 레벨에서 동적으로 형이 정의됩니다.(이 얼마나 편한가...)

 

package main

import "fmt"

var i, j int = 1, 2

func main() {
	var foo, bar = 10, false;
	fmt.Println(foo, bar);
	fmt.Println(foo + i, bar, j)
}

 

전역 변수로 선언된 i, j는 형 선언과 동시에 값 초기화가 이루어졌습니다. 하지만 그렇게 안 해도 되는 게 main() 내부를 들여다보면 foo와 bar는 초깃값의 타입이 다름에도 불구하고 선언이 오류 없이 진행되며, 값 또한 대입되었습니다. 이런 점은 고의 강점이라고 볼 수 있겠죠. 정적 선언과 동적 선언을 프로그래머 레벨에서 해도 되며, 안 해도 되지만, 통일성을 위해선 하나의 패스만 지향해야 합니다. 물론 컴파일 레벨에서는 정적 선언된 변수를 읽는 속도가 동적 변수를 읽는 속도보다 월등히 빠르다는 점은 인지하고 계셔야 합니다! 이유로는, 상황을 가정해보겠습니다.

 

 

사과는 빨갛지만 초록색 사과도 존재하죠? 만약 누군가가 사과를 사와달라고 부탁했습니다.  하지만 마트에 들어선 여러분 개개인은 모두 고민에 빠집니다. 초록색을 살지 빨간색을 살지, 부탁했으니 나의 취향대로 사다 주어도 그만이겠지만, 현실은 그렇지 못하죠? 하지만 부탁한 사람이 빨간색 사과를 사 와 달라고 했다면, 고민할 필요 없이 바로 살 수 있으니 얼마나 시간 절약이 될까요! 컴파일러도 이와 동일합니다. 알고 컴파일하는 것과 모르고 컴파일 과정 중 추론하는 것은 쉬운 일이 아니라는 겁니다!! 

 

:= Declare

함수 내부에서는 :=라는 키워드를 통해 var키워드 없이 var 키워드로 선언된 변수로 사용할 수 있습니다. 다만 주의해야할 점은 함수 외부에서는 모든 선언에 키워드가 붙으므로 이는 사용할 수 없습니다. 물론 컴파일도 안 되겠지만요

 

package main

import "fmt"

func main() {
	var foo, bar = 10 ,15
	zoo := 20
	
	fmt.Println(foo + zoo, bar + zoo)
}

 

위 코드와 같이 사용 가능하지만, 절대 함수 외부에서는 선언하는 바보 같은 일은 없어야 합니다!

 

Variables Type

고는 다양한 타입의 기본 타입을 제공합니다! 그렇다고 복잡하게 생각할 필요는 없습니다. 사용하는 타입만 사용하게 되는 것도 있고, 특수한 상황을 제외한 상황에서만 익숙하지 않은 타입이 사용되니까요!

 

bool -> true or false
string -> 당연히 문자열이죠?
int -> Integer
subtype of int -> int8, int16, int32, int 64
uint-> Unsigned Integer
subtype of uint -> uint8, uint16, uint32, uint64

byte -> alias of uint8

rune -> alias of int32

float32, float64
complex64, complex12

 

타입은 위 코드와 같이 존재합니다. 하지만 특수한 상황을 제외하고는 사용하는 친구들만 사용할 테니까요 그렇게 신경 안 써도 됩니다!! 이런 게 있구나 하세요 지금은:)

 

package main

import (
	"fmt"
)

var (
	foo   bool       = false
	MaxIntValue uint64     = 1<<64-1
)

func main() {
	fmt.Printf("Type: %T Value: %v\n", foo, foo)
	fmt.Printf("Type: %T Value: %v\n", MaxIntValue, MaxIntValue)
}

 

일반적으로 int와 uintptr 타입은 일반적인 퍼스널 컴퓨터 시스템인 32-bit시스템에서의 32bit 또는 64bit의 길이를 지닙니다. 특정한 이유로 정수의 길이를 제한하지 않는 상 int타입을 이용해 정수형 변수를 선언하는 것이 옳습니다!! 이후에 배울 내용이지만 특별한 키워드가 보입니다. var ( -- ) 내부에 변수가 선언돼있는 형태입니다. 위에서 말씀드렸듯이, 함수 내부가 아닌 이상 변수는 선제적으로 var키워드를 이용한 선언 및 초기화가 진행된다고 말씀드렸습니다. 물론 var키워드를 사용해도 되지만, 다중 선언 시에는 위와 같이 선언 해주면 됩니다! 간단하게 타입 변환 이전에 zero values에 대해서 알아보도록 하겠습니다. 변수의 선언시에 초깃값이 존재하지 않는 경우에는 0이라는 값을 임시적으로 대입하게 됩니다. 그러니까,

 

var Num int // == var Num int = 0
var isOk bool // == var isOk bool = false
var name string // == var name string = ""

 

위와 같이 말이죠! 

 

Type Casting

형 변환은 말 그대로 변수의 형 즉, 타입을 다른 타입으로 변환시키는 것을 의미합니다. 그러니까 아래와 같은 형태란 말이죠,

 

var Var int = 1
Type(Var) // float64 or uint...? whatever you want

 

변수의 이름을 묶어서 형 변환을 합니다. 이러한 형태는 다른 언어에서도 쉽사리 찾아볼 수 있죠. 그렇다면 어떻게 구현될지 보도록 하겠습니다.

 

package main

import (
	"fmt"
)


var (
	foo int = 3
	bar int = 10
)

func main() {
	var zoo float64 = float64(foo * bar)/2.3
	var z uint = uint(zoo)
	fmt.Println(foo, zoo, z)
}

 

전역 변수 foo, bar가 존재합니다. 이 변수들은 zoo라는 변수에 곱해져 float64 타입으로 캐스팅 되어, 2.3으로 나누어줍니다. 물론 이또한 float64타입으로 캐스팅됐기 때문에 divide가 가능하다는 점을 간과해선 안됩니다! 결괏값 또한 정상적으로 출력되며 눈으로 형 변환을 확인할 수 있습니다.

 

$ 3 13.043478260869566 13

 

보시다시피 uint로 캐스팅되어 소수점 아래 영역은 제거된 것을 확인할 수 있습니다. 비교적 간단한 방식으로 형 변환은 완료됩니다. 

 

Const Type

  상수는 변수와 동일하게 선언됩니다. 고의 어떤 타입이든 상수 타입이 될 수 있습니다. 아래의 문법을 지닙니다.

 

const (VAR_NAME) = (INITIAL_VALUE)

 

상수는 모두가 알다시피 불변 값으로 선언되는 변수를 일컫는 키워드입니다. 그러니까 다시금 변수의 값을 임의적으로 변경하는 것이 불가능하다는 것입니다.

 

package main

import "fmt"

const Pi float64 = 3.14

func main(){
	const foo int64 = 256
	const bar string = "Gildong"
	fmt.Println(Pi, foo, bar)
	// foo = 12; can't assign to foo error occur
}

 

만약 새로운 값을 대입하고자 하면 아래와 같이 컴파일러는 오류를 반환합니다. 당연히 상수값으로 초기화된 변수인데 거기다가 새로운 변수를 넣는다는 것은 말이 안 되죠, 보통 프로그램 내부에서 값이 변경될 일이 없는, 타입 안전성을 지녀야 하는 변수는 const키워드를 이용해 상수 변수로 사용합니다.

 

이번 시간에 변수와 상수에 대해서 학습해보았는데, 책만큼은 아니지만 이때까지 제가 학습한 내용을 토대로 최대한 자세하게 설명하려고 노력했습니다. 부족한 점이 보인다면 댓글에 남겨주시면 감사하겠습니다!!!ㅜㅜㅜ

 

글 잘 읽으셨다면 공감 하트 한번 눌러주시면 감사하겠습니다!!

 

댓글로 피드백, 문의, 질문 모두 환영하니까 편하게 달아주시면 감사하겠습니다!!

 

 

읽어주셔서 감사합니다 모두들~😍😍😍😍😍😍

 

 

다음 편!!! ---->

hazarddev.tistory.com/66

 

[Go#3] Go언어 패키지, import-export, function 이해하기!!!

Powerful Concurrency Language Go 저희 저번 시간에는 고 언어의 변수의 타입과 타입 캐스팅에 대해서 알아보았습니다. 물론 만약 못 보신 분이 계시다면 아래 링크를 통해서 보고 오시는 것을 추천드립

hazarddev.tistory.com

 

728x90

댓글