연산자

연산자

Go언어의 연산자를 알아보자.


연산자란

이전 배웠던 변수와 상수는 값을 저장하는 기능만 합니다. 따라서 저장한 값을 가지고 연산을 하기 위해서는 '연산자'를 사용해야합니다.
연산자의 종류와 기능은 다른 언어들과 비슷하지만 몇 가지 주의해야할 점이 있으므로 살펴보기를 바랍니다.

수식 연산자

수식 연산자는 두 개의 피연산자를 요구하는 이항 연산자(binary operator)입니다. 표

package main

import "fmt"

func main() {
	num1, num2 := 17, 5
	str1, str2 := "Hello", "goorm!"
	
	fmt.Println("num1 + num2 =", num1+num2)
	fmt.Println("str1 + str2 =", str1+str2)
	fmt.Println("num1 - num2 =", num1-num2)
	fmt.Println("num1 * num2 =", num1*num2)
	fmt.Println("num1 / num2 =", num1/num2)
	fmt.Println("num1 % num2 =", num1%num2)
}

증감 연산자

Go언어에서 증감 연산자를 사용할 때 주의할 점이 두 가지가 있습니다.
첫 번째는 증감 연산자를 사용하고 동시에 대입할 수 없습니다.
두 번째는 전위 연산을 할 수 없습니다. 아래 예시가 있습니다.

num := count++ (X)
++count (X)

표

package main

import "fmt"

func main() {
	count1, count2 := 1, 10.4
	
	count1++
	count2--
	
	fmt.Println("count1++ :", count1)
	fmt.Println("count2-- :", count2)
}

할당 연산자

할당 연산자는 값을 단순히 대입하는 대입 연산자와 연산 후 값을 바로 대입시키는 복합 대입 연산자가 있습니다.
표

package main

import "fmt"

func main() {
	a := 2
	var num int

	num = a
	fmt.Println("num = a :", num)
	num += 4
	fmt.Println("num += 4 :", num)
	num -= 2
	fmt.Println("num -= 2 :", num)
	num *= 5
	fmt.Println("num *= 5 :", num)
	num /= 2
	fmt.Println("num /= 2 :", num)
	num %= 3
	fmt.Println("num %= 3 :", num)

	num = 3  //00000011
	num &= 2 //00000010
	fmt.Printf("num &= 2 : %08b, %d\n", num, num)
	num |= 5 //00000101
	fmt.Printf("num |= 5 : %08b, %d\n", num, num)
	num ^= 4 //00000100
	fmt.Printf("num ^= 4 : %08b, %d\n", num, num)
	num &^= 2 //00000010
	fmt.Printf("num &^= 2 : %08b, %d\n", num, num)
	num <<= 9 //00001001
	fmt.Printf("num <<= 9 : %08b, %d\n", num, num)
	num >>= 8 //00001000
	fmt.Printf("num >>= 8 : %08b, %d\n", num, num)
}

논리 연산자

Go언어에서 논리부정 연산시 bool 형의 선언 및 사용만이 가능합니다. 즉, false와 true값만 사용할 수 있습니다.
아래 예시가 있습니다. var a int = 10, b := 1 일 때,

fmt.Println(!a) (X)
fmt.Println(!b) (X)

표

package main

import "fmt"

func main() {
	var a bool = true
	b := false

	fmt.Println("0 && 0 : ", b && b)
	fmt.Println("0 && 1 : ", b && a)
	fmt.Println("1 && 1 : ", a && a)
	fmt.Println("0 || 0 : ", b || b)
	fmt.Println("0 || 1 : ", b || a)
	fmt.Println("1 || 1 : ", a || a)

	fmt.Println("!1 ", !true)
	fmt.Println("!0 ", !false)
}

관계 연산자

관계 연산자는 두 값의 대소와 동등의 관계를 따지는 연산자입니다.
표

package main

import "fmt"

func main() {
	fmt.Println("13 == 13 : ", 13 == 13)
	fmt.Println("13 == 23 : ", 13 == 23)
	fmt.Println("13 != 13 : ", 13 != 13)
	fmt.Println("3 != 5 : ", 3 != 5)
	fmt.Println("0 < 1 : ", 0 < 1)
	fmt.Println("0 > 1 : ", 0 > 1)
	fmt.Println("0 >= 1 : ", 0 >= 1)
	fmt.Println("0 <= 1 : ", 0 <= 1)
}

비트 연산자

비트 연산자는 사실 기계에 좀 더 친화적인 연산자지만 다른 영역에도 사용돼 효율성을 높이고 연산의 수를 줄이는 요인이 되기도 합니다. 활용적 측면을 이해하기엔 큰 부담이 따르기 때문에 연산자의 기능을 이해하는 데 초점을 맞추어 정리합니다.
표

package main

import "fmt"

func main() {
	num1 := 15 //00001111
	num2 := 20 //00010100

	fmt.Printf("num1 & num2 : %08b, %d\n", num1&num2, num1&num2)
	fmt.Printf("num1 | num2 : %08b, %d\n", num1|num2, num1|num2)
	fmt.Printf("num1 ^ num2 : %08b, %d\n", num1^num2, num1^num2)
	fmt.Printf("num1 &^ num2 : %08b, %d\n", num1&^num2, num1&^num2)

	fmt.Printf("num1 << 4 : %08b, %d\n", num1<<4, num1<<4)
	fmt.Printf("num2 >> 2 : %08b, %d\n", num2>>2, num2>>2)
}

채널 연산자

Go언어는 채널이라는 개념이 있습니다. 간단히 말하자면 채널이랑 고루틴(goroutine)끼리 데이터를 주고 받고 실행 흐름을 제어하는 기능입니다.
표

package main

import "fmt"

func main() {
	ch := make(chan int) //정수형 채널 생성

	go func() {
		ch <- 10
	}() //채널에 10을 보냄

	result := <-ch //채널로부터 10을 전달받음
	fmt.Println(result)
}

포인터 연산자

Go언어는 포인터 연산자(&, *)를 제공하지만 포인터 산술 즉, 포인터에 더하고 빼는 기능은 제공하지 않습니다.
표

package main

import "fmt"

func main() {
	var num int = 5
	var pnum = &num

	fmt.Println("num : ", num)   //num 값
	fmt.Println("pnum :", pnum)  //num의 메모리 주소
	fmt.Println("pnum :", *pnum) //num의 주소로 메모리에 할당돼있는 값 접근

	*pnum++
	fmt.Println("num : ", num)
	fmt.Println("pnum :", *pnum)
	//포인터 연산자를 이용한 값 변경
}

연산자 우선순위

한 수식 안에 여러 연산자가 있으면 어떤 순서로 연산을 하는지 모릅니다. 가령, "덧셈, 뺄셈보다는 곱셈, 나눗셈을 먼저 계산해야한다."는 것이 '연산자 우선순위'입니다. 그리고 같은 순위의 연산자는 왼쪽부터 순서대로 계산합니다. 이것이 바로 '결합방향'입니다.
표


© 2022. All rights reserved. 신동민의 블로그