[Go] #3.1 연산자 종류
강의 링크 : 한 눈에 끝내는 고랭 기초 #3 연산자 - 연산자 종류
0. Go 학습 재개
원래 스터디 당초 계획은 3일에 한 번씩 진도를 나가는 것이었으나 …
졸업 작품 + 취업 과제, 면접으로 인해 한 달이 쫙 밀려버렸다.
나 대신 스터디를 진행해준 스터디원의 양해에 감사하며 다시 열심히 해봐야겠다.
1. 연산자 종류
어떤 언어를 배우든 그에 맞는 연산자가 존재한다.
Go
에서의 여러가지 연산자에 대해서 알아보자.
I. 수식 연산자
수식 연산자는 두 개의 피연산자를 요구하는 이항 연산자(binary operator)이다.
다른 언어들과 마찬가지로 기본적인 사칙연산, 나머지 값 반환 연산자가 있다.
종류 | 기능 | 설명 |
---|---|---|
+ | 피연산자의 값을 더한다. | 값의 자료형은 정수, 실수, 복소수, 문자열입니다. |
- | 왼쪽의 피연산자 값에서 오른쪽의 피연산자 값을 뺀다. | 값의 자료형은 정수, 실수, 복소수입니다. |
* | 피연산자의 값을 곱한다. | 값의 자료형은 정수, 실수, 복소수입니다. |
/ | 왼쪽의 피연산자 값을 오른쪽의 피연산자 값으로 나눈다. | 값의 자료형은 정수, 실수, 복소수입니다. |
% | 왼쪽의 피연산자 값을 오른쪽의 피연산자 값으로 나눴을 때 얻게 되는 나머지 값을 반환한다. ex) num := 7 % 2 (num = 1이 할당됨) | 값의 자료형은 정수, 실수, 복소수입니다. |
+
연산자는 문자열 결합도 가능함에 주의.
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)
}
// 실행결과
num1 + num2 = 22
str1 + str2 = Hellogoorm!
num1 - num2 = 12
num1 * num2 = 85
num1 / num2 = 3
num1 % num2 = 2
II. 증감 연산자
C++
과 동일하지만, 주의할 점이 있다.
- 증감 연산자를 사용함과 동시에 대입할 수 없다.
- ex) num := count++ (X)
- 전위 연산을 할 수 없다.
- ex) ++count (X)
종류 | 기능 | 설명 |
---|---|---|
++ | 값을 1 증가시킨다. | 값의 자료형은 정수, 실수, 복소수입니다. |
– | 값을 1 감소시킨다. | 값의 자료형은 정수, 실수, 복소수입니다. |
package main
import "fmt"
func main() {
count1, count2 := 1, 10.4
count1++
count2--
fmt.Println("count1++ :", count1)
fmt.Println("count2-- :", count2)
}
// 실행결과
count1++ : 2
count2-- : 9.4
III. 할당 연산자
할당 연산자는 값을 단순히 대입하는 대입 연산자
와 연산 후 값을 바로 대입시키는 복합 대입 연산자
가 있다.
다른 언어와 거의 동일하다.
종류 | 기능 | 설명 |
---|---|---|
= | 변수나 상수에 값을 대입한다. | 변수는 변수끼리 대입이 가능합니다. |
:= | 변수를 선언 및 대입한다. | |
:= | 변수를 선언 및 대입한다. | |
+= | 값을 더한 후 대입한다. | 문자열일 경우 현재 변수에 문자열을 이어 붙인 다음 변수에 대입합니다. |
*= | 값을 곱한 후 대입한다. | |
/= | 값을 나눈 후 대입한다. | |
%= | 값의 나눗셈 후 나머지를 대입한다. | |
&= | 값의 AND 비트 연산 후 대입한다. | |
|= | 값의 OR 비트 연산 후 대입한다. | |
^= | 값의 XOR 비트 연산 후 대입한다. | |
&^= | 값의 AND NOT 비트 연산 후 대입한다. | |
«= | 비트를 왼쪽으로 이동 후 대입한다. | |
»= | 비트를 오른쪽으로 이동 후 대입한다. |
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)
}
// 실행결과
num = a : 2
num += 4 : 6
num -= 2 : 4
num *= 5 : 20
num /= 2 : 10
num %= 3 : 1
num &= 2 : 00000010, 2
num |= 5 : 00000111, 7
num ^= 4 : 00000011, 3
num &^= 2 : 00000001, 1
num <<= 9 : 1000000000, 512
num >>= 8 : 00000010, 2
IV. 논리 연산자
AND(논리곱)
, OR(논리합)
, NOT(논리부정)
을 연산한다.
마찬가지로 다른 언어들과 거의 동일하다.
주의할 점은 Go
에서는 NOT
연산시 bool
형의 선언 및 사용만이 가능하다.
즉, false
, true
값만 사용할 수 있다.
아래 예시를 보자.
var a int = 10, b := 1
fmt.Println(!a) // 불가능
fmt.Println(!b) // 불가능
종류 | 기능 | 설명 |
---|---|---|
&& | 연산하는 A와 B모두 ‘참’이면 연산 결과로 ‘참’을 반환한다. | 1&&0=0 1&&1=1 0&&0=0 |
|| | 연산하는 A와 B 둘 중 하나라도 ‘참’이면 연산 결과로 ‘참’을 반환한다. | 1||0=1 1||1=1 0||0=0 |
! | 연산하는 A가 ‘참’이면 ‘거짓’, ‘거짓’이면 ‘참’을 반환한다. | !1=0 !0=1 |
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)
}
// 실행결과
0 && 0 : false
0 && 1 : false
1 && 1 : true
0 || 0 : false
0 || 1 : true
1 || 1 : true
!1 false
!0 true
V. 관계 연산자
관계 연산자는 두 값의 대소와 동등의 관계를 따지는 연산자이다.
관계 연산자는 조건을 만족하면 true
를, 만족하지 않으면 false
를 반환한다.
종류 | 기능 | 설명 |
---|---|---|
== | 두 값이 같은지 비교한다. | 같을 경우 ‘true’, 다를 경우 ‘false’를 반환한다. |
!= | 두 값이 다른지 비교한다. | 다를 경우 ‘true’, 같을 경우 ‘false’를 반환한다. |
< | 오른쪽 값이 큰지 비교한다. | 오른쪽 값이 큰 경우 ‘true’, 그렇지 않을 경우 ‘false’를 반환한다. |
<= | 오른쪽 값이 크거나 같은지 비교한다. | 오른쪽 값이 크거나 같은 경우 ‘true’, 그렇지 않을 경우 ‘false’를 반환한다. |
> | 왼쪽 값이 큰지 비교한다. | 왼쪽 값이 큰 경우 ‘true’, 그렇지 않을 경우 ‘false’를 반환한다. |
>= | 왼쪽 값이 크거나 같은지 비교한다. | 왼쪽 값이 크거나 같은 경우 ‘true’, 그렇지 않을 경우 ‘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)
}
// 실행 결과
13 == 13 : true
13 == 23 : false
13 != 13 : false
3 != 5 : true
0 < 1 : true
0 > 1 : false
0 >= 1 : false
0 <= 1 : true
VI. 비트 연산자
비트 연산자는 비트 단위의 연산을 수행한다.
나한테는 PS를 할 때 비트마스킹 등으로 익숙하다.
종류 | 기능 | 설명 |
---|---|---|
& | 두 값을 비트 단위로 AND 연산을 한다. | |
| | 두 값을 비트 단위로 OR 연산을 한다. | |
^ | 두 값을 비트 단위로 XOR 연산을 한다. | 사용할 수 있는 값의 자료형은 정수입니다. |
&^ | 두 값을 비트 단위로 AND NOT 연산을 한다. | 사용할 수 있는 값의 자료형은 정수입니다. |
« | 값의 비트 열을 왼쪽으로 이동시킨다. | 사용할 수 있는 값의 자료형은 정수입니다. |
» | 값의 비트 열을 오른쪽으로 이동시킨다. | 사용할 수 있는 값의 자료형은 정수입니다. |
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)
}
// 실행 결과
num1 & num2 : 00000100, 4
num1 | num2 : 00011111, 31
num1 ^ num2 : 00011011, 27
num1 &^ num2 : 00001011, 11
num1 << 4 : 11110000, 240
num2 >> 2 : 00000101, 5
VII. 채널 연산자
Go
언어에는 채널
이라는 개념이 있다.
간단히 말하자면 채널
이랑 고루틴(goroutine)
끼리 데이터를 주고 받고 실행 흐름을 제어하는 기능이다.
채널 연산자
는 채널
을 사용할때 쓰는 연산자이다.
처음으로 아예 색다른 연산자가 나왔다.
지금은 그런가보다 하고 넘어가고 채널에 대해 자세한건 이후에 배워보자.
종류 | 기능 | 설명 |
---|---|---|
<- | 채널의 수신을 연산한다. | 채널에 값을 보내거나 가져옵니다. |
package main
import "fmt"
func main() {
ch := make(chan int) //정수형 채널 생성
go func() {
ch <- 10
}() //채널에 10을 보냄
result := <-ch //채널로부터 10을 전달받음
fmt.Println(result)
}
// 실행 결과
10
VIII. 포인터 연산자
포인터 연산자는 C++
과 같이 &
와 *
연산자를 이용해 메모리에 접근할 수 있도록 한다.
주의할 점은 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)
//포인터 연산자를 이용한 값 변경
}
// 실행 결과
num : 5
pnum : 0xc0000160c8
pnum : 5
num : 6
pnum : 6
마무리
대부분의 연산자는 다른 언어들에서 최소 한 번씩은 본 연산자들이지만, 채널 연산자
는 처음이라 조금 색달랐다.
다른건 없고, 증감 연산자
, 논리 연산자
, 포인터 연산자
의 주의사항 정도만 확인하고 넘어가면 될 것 같다.