Operator | Name | Requirements for the Two Operands |
---|---|---|
+ |
addition
|
The two operands must be both values of the same basic numeric type.
|
- |
subtraction
|
|
* |
multiplication
|
|
/ |
division
|
|
% |
remainder
|
The two operands must be both values of the same basic integer type.
|
Operator | Name | Requirements for the Two Operands and Mechanism Explanations |
---|---|---|
&
|
bitwise and |
The two operands must be both values of the same integer type.
Mechanism explanations (a value with the subscript
2 is the binary literal form of the value):
|
|
|
bitwise or | |
^
|
bitwise xor | |
&^
|
bitwise clear | |
<<
|
bitwise left shift |
The left operand must be an integer and the right operand must be also an integer (if it is a constant, then it must be non-negative), their types are not required to be identical. (Note, before Go 1.13, the right operand must be an unsigned integer or an untyped integer constant which is representable as an
uint value.)
A negative right operand (must be a non-constant) will cause a panic at run time.
Mechanism explanations:
Note: in a bitwise-right-shift operation, all the freed-up bits at left are filled with the sign bit (the highest bit) of the left operand. For example. if the left operand is an
int8 value -128 , or 100000002 in the binary literal form, then 10000000$$2$$ >> 2 results 111000002 , a.k.a., -32 .
|
>>
|
bitwise right shift |
Operator | Name | Explanations |
---|---|---|
+
|
positive |
+n is equivalent to 0 + n .
|
-
|
negative |
-n is equivalent to 0 - n .
|
^
|
bitwise complement (bitwise not) |
^n is equivalent to m ^ n , where m is a value all of which bits are 1. For example, if the type of n is int8 , then m is -1 , and if the type of n is uint8 , then m is 0xFF .
|
~
.
+
can also be used as string concatenation operator, which will be introduced below.
*
can also be used as pointer dereference operator, and the bitwise-and operator &
can also be used as address taking operator. Please read pointers in Go for details later.
>>>
doesn't exist in Go.
Pow
function in the math
standard package instead. Code package and package import will be introduced in the next article packages and imports.
&^
is a unique operator in Go. m &^ n
is equivalent to m & (^n)
.
func main() {
var (
a, b float32 = 12.0, 3.14
c, d int16 = 15, -6
e uint8 = 7
)
// The ones compile okay.
_ = 12 + 'A' // two numeric untyped operands
_ = 12 - a // one untyped and one typed operand
_ = a * b // two typed operands
_ = c % d
_, _ = c + int16(e), uint8(c) + e
_, _, _, _ = a / b, c / d, -100 / -9, 1.23 / 1.2
_, _, _, _ = c | d, c & d, c ^ d, c &^ d
_, _, _, _ = d << e, 123 >> e, e >> 3, 0xF << 0
_, _, _, _ = -b, +c, ^e, ^-1
// The following ones fail to compile.
_ = a % b // error: a and b are not integers
_ = a | b // error: a and b are not integers
_ = c + e // error: type mismatching
_ = b >> 5 // error: b is not an integer
_ = c >> -5 // error: -5 is not representable as uint
_ = e << uint(c) // compiles ok
_ = e << c // only compiles ok since Go 1.13
_ = e << -c // only compiles ok since Go 1.13,
// will cause a panic at run time.
_ = e << -1 // error: right operand is negative
}
// Results are non-constants.
var a, b uint8 = 255, 1
// Compiles ok, higher overflowed bits are truncated.
var c = a + b // c == 0
// Compiles ok, higher overflowed bits are truncated.
var d = a << b // d == 254
// Results are untyped constants.
const X = 0x1FFFFFFFF * 0x1FFFFFFFF // overflows int
const R = 'a' + 0x7FFFFFFF // overflows rune
// The above two lines both compile ok, though the
// two untyped value X and R both overflow their
// respective default types.
// Operation results or conversion results are
// typed values. These lines all fail to compile.
var e = X // error: untyped constant X overflows int
var h = R // error: constant 2147483744 overflows rune
const Y = 128 - int8(1) // error: 128 overflows int8
const Z = uint8(255) + 1 // error: 256 overflow uint8
int
, rune
, float64
, complex128
. For example, if the default type of one untyped operand is int
, and the other one is rune
, then the default type of the result untyped value is rune
.
int
. For such cases, the result is also an untyped value and the default type of the result is the same as the left operand.
func main() {
// Three untyped values. Their default
// types are: int, rune(int32), complex64.
const X, Y, Z = 2, 'A', 3i
var a, b int = X, Y // two typed values.
// The type of d is the default type of Y: rune.
d := X + Y
// The type of e is the type of a: int.
e := Y - a
// The type of f is the types of a and b: int.
f := a * b
// The type of g is Z's default type: complex64.
g := Z * Y
// Output: 2 65 (+0.000000e+000+3.000000e+000i)
println(X, Y, Z)
// Output: 67 63 130 (+0.000000e+000+1.950000e+002i)
println(d, e, f, g)
}
const N = 2
// A is an untyped value (default type as int).
const A = 3.0 << N // A == 12
// B is typed value (type is int8).
const B = int8(3.0) << N // B == 12
var m = uint(32)
// The following three lines are equivalent to
// each other. In the following two lines, the
// types of the two "1" are both deduced as
// int64, instead of int.
var x int64 = 1 << m
var y = int64(1 << m)
var z = int64(1) << m
// The following line fails to compile.
/*
var _ = 1.23 << m // error: shift of type float64
*/
1
is deduced as int
instead of int64
, the bitwise operation at line 13 (or line 12) will return different results between 32-bit architectures (0) and 64-bit architectures (232), which may produce some bugs hard to detect in time.
const n = uint(2)
var m = uint(2)
// The following two lines compile okay.
var _ float64 = 1 << n
var _ = float64(1 << n)
// The following two lines fail to compile.
var _ float64 = 1 << m
var _ = float64(1 << m)
var _ = float64(1) << m
var _ = 1.0 << m // error: shift of type float64
package main
const n = uint(8)
var m = uint(8)
func main() {
println(a, b) // 2 0
}
var a byte = 1 << n / 128
var b byte = 1 << m / 128
2 0
, because the last two lines are equivalent to
var a = byte(int(1) << n / 128)
var b = byte(1) << m / 128
x
and y
are two operands of the same integer type, the integer quotient q
(= x / y
) and remainder r
(= x % y
) satisfy x == q*y + r
, where |r| < |y|
. If r
is not zero, its sign is the same as x
(the dividend). The result of x / y
is truncated towards zero.
y
is a constant, it must not be zero. If the divisor is zero at run time and it is an integer, a run-time panic occurs. Panics are like exceptions in some other languages. We can learn more about panics in this article.
println( 5/3, 5%3) // 1 2
println( 5/-3, 5%-3) // -1 2
println(-5/3, -5%3) // -1 -2
println(-5/-3, -5%-3) // 1 -2
println(5.0 / 3.0) // 1.666667
println((1-1i)/(1+1i)) // -1i
var a, b = 1.0, 0.0
println(a/b, b/b) // +Inf NaN
_ = int(a)/int(b) // compiles okay but panics at run time.
// The following two lines fail to compile.
println(1.0/0.0) // error: division by zero
println(0.0/0.0) // error: division by zero
op=
for binary arithmetic operators
op
, x = x op y
can be shortened to x op= y
. In the short form, x
will be only evaluated once.
var a, b int8 = 3, 5
a += b
println(a) // 8
a *= a
println(a) // 64
a /= b
println(a) // 12
a %= b
println(a) // 2
b <<= uint(a)
println(b) // 20
++
and decrement --
operators
++
and decrement --
operators. However, operations using the two operators don't return any results, so such operations can not be used as expressions. The only operand involved in such an operation must be a numeric value, the numeric value must not be a constant, and the ++
or --
operator must follow the operand.
package main
func main() {
a, b, c := 12, 1.2, 1+2i
a++ // ok. <=> a += 1 <=> a = a + 1
b-- // ok. <=> b -= 1 <=> b = b - 1
c++ // ok
// The following lines fail to compile.
/*
_ = a++
_ = b--
_ = c++
++a
--b
++c
*/
}
Operator | Name | Requirements for the Two Operands |
---|---|---|
+
|
string concatenation |
The two operands must be both values of the same string type.
|
op=
form also applies for the string concatenation operator.
println("Go" + "lang") // Golang
var a = "Go"
a += "lang"
println(a) // Golang
Operator | Name | Requirements for the Two Operands |
---|---|---|
&&
|
boolean and (binary) a.k.a. conditional and |
The two operands must be both values of the same boolean type.
|
boolean or (binary) a.k.a. conditional or |
||
!
|
boolean not (unary) |
The type of the only operand must be a boolean type.
|
!=
operator introduced in the next sub-section as the boolean xor operator.
// x y x && y x || y !x !y
true true true true false false
true false false true false true
false true false true true false
false false false false true true
Operator | Name | Requirements for the Two Operands |
---|---|---|
==
|
equal to |
Generally, the types of its two operands must be the same. For detailed rules, please read comparison rules in Go.
|
!=
|
not equal to | |
<
|
less than |
The two operands must be both values of the same integer type, floating-point type or string type.
|
<=
|
less than or equal to | |
>
|
larger than | |
>=
|
larger than or equal to |
==
and !=
operators. We will learn that values of which types are not comparable later. Values of basic types are all comparable.
()
can be used to promote precedence.
* / % << >> & &^
+ - | ^
== != < <= > >=
&&
||
<<
and >>
is higher than +
and -
in Go.
2.2
instead of 2.7
. The reason is the precedence of the division operation is higher than the addition operation, and in the division operation, both 3
and 2
are viewed as integers. The evaluation result of 3/2
is 1
.
var x = 1.2 + 3/2
3
and 2
are viewed as integers. However, in the second declaration, they are both viewed as floating-point numbers.
package main
const x = 3/2*0.1
const y = 0.1*3/2
func main() {
println(x) // +1.000000e-001
println(y) // +1.500000e-001
}
*
and &
. Yes the same operator symbols as the multiplication and bitwise-and operators. &
is used to take the address of an addressable value, and *
is used to dereference a pointer value. Unlike C/C++, in Go, values of pointer types don't support arithmetic operations. For more details, please read pointers in Go later.
The Go 101 project is hosted on Github. Welcome to improve Go 101 articles by submitting corrections for all kinds of mistakes, such as typos, grammar errors, wording inaccuracies, description flaws, code bugs and broken links.
If you would like to learn some Go details and facts every serveral days, please follow Go 101's official Twitter account @zigo_101.
reflect
standard package.sync
standard package.sync/atomic
standard package.