很多程序员都是从c/c++转到go的,难免会产生一些混淆, 在学习go语言的时候,尤其要注意与c/c++的区别, 对比起来学习效果可能更好。下面这个总结很不错, 直接引用过来学习:http://hyperpolyglot.org/c
Hyperpolyglot
C, Go
a side-by-side reference sheet
grammar and invocation | variables and expressions | arithmetic and logic | strings | regexes | dates and time | fixed-length-arrays | resizable arrays | dictionaries | functions | execution control | concurrency | file handles | files | directories| processes and environment | option parsing | libraries and namespaces | user-defined types | c preprocessor macros | net and web | unit tests | debugging and profiling
version | ||
---|---|---|
c | go | |
version used |
C11, gcc 4.8, clang 3.5 | 1.4 |
show version |
$ gcc --version | $ go version |
implicit prologue | #include <errno.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <time.h> #include <wchar.h> |
import "fmt" |
grammar and invocation | ||
c | go | |
hello world | $ cat hello.c #include <stdio.h> int main(int argc, char **argv) { printf("Hello, World!\n"); } $ gcc hello.c $ ./a.out Hello, World! |
$ cat hello.go package main import "fmt" func main() { fmt.Printf("Hello, World!\n") } $ go build hello.go $ ./hello Hello, World! |
file suffixes source, header, object file |
.c .h .o | |
statement separator | ; | ; or sometimes newline a new line terminates a statement when the last token on the line is (1) an identifier, (2) a numeric, character, or string literal, (3) one of the keywords break, continue, fallthrough, or return, (4) one of ++, --, ), ], or } |
block delimiters |
{ … } | { … } |
end-of-line comment |
// comment | // comment |
multiple line comment | /* comment line another line */ |
/* comment line another line */ |
variables and expressions | ||
c | go | |
variable | /* if inside function, memory allocated on stack: */ int i; int j = 3; /* memory allocated on heap: */ int *ptr = malloc(sizeof *ptr); /* if malloc fails, it returns NULL and sets errno to ENOMEM */ *ptr = 7; |
// memory allocated on stack: var i int // allocated on stack; type inferred from literal: j := 3 // memory allocated on heap: ptr := new(int) *ptr = 7 |
free heap |
free(ptr); | none; uses garbage collection |
global variable | /* in foo.c, outside of any function: */ int x = 7; /* to declare in bar.c: */ extern int x; |
// foo.go: package foo // capitalized top-level identifiers are exported: var X = 7 // bar.go: package bar import foo // package scope: var y = 3 func baz() { // local scope: var z = 5 fmt.Println(foo.X + y + z) } |
uninitialized variable | The behavior of reading from uninitialized stack variables or unitialized memory allocated by malloc is undefined. Global and static variables are zero-initialized. Heap variables allocated by calloc have their bytes zeroed. |
Every type has a zero value. For numeric types it is zero and for strings it is the empty string. |
compile time constant | /* usually preprocessor is used: */ #define PI 3.14 |
const Pi = 3.14 |
immutable variable | const int i = rand(); | none |
assignment | i = 3; | // defines variable of appropriate type: i := 3 // variable must already be declared: i = 3 |
parallel assignment | none | // define variables of appropriate type: m, n := 3, 7 // x and y must already be declared: x, y = 2, 8 |
swap | int x = 1, y = 2, tmp; tmp = x; x = y; y = tmp; |
x, y = y, x |
compound assignment | arithmetic: += -= *= /= %= bit: <<= >>= &= |= ^= |
arithmetic: += -= *= /= %= bit: <<= >>= &= |= ^= |
increment and decrement | premodifiers: ++i --i postmodifiers: i++ i-- |
postmodifiers only; cannot be used in expressions: i++ i-- |
address | int i = 3; int* ptr = &i; |
i := 3 var ptr *int ptr = &i ptr2 := &i |
dereference |
int i2 = *ptr; | i2 := *ptr |
type size | /* put type inside parens: */ sizeof (int) /* expressions and values don't require parens: */ sizeof 1 + 1 |
import "unsafe" // use expression or name of variable with type: unsafe.Sizeof(i) unsafe.Sizeof(1 + 1) |
address arithmetic | int a[] = {3, 2, 1, 0}; for (int *p = a; *p; ++p) { printf("%d\n", *p); } |
none |
null |
/* pointer types only: */ NULL |
// cannot be stored in numeric or string variable: nil |
null test |
ptr == NULL | ptr == nil |
conditional expression |
x > 0 ? x : -x | none |
arithmetic and logic | ||
c | go | |
boolean type |
int /* includes type for consistency with C++: */ #include <stdbool.h> bool |
bool |
true and false |
1 0 /* includes identifiers for consistency with C++: */ #include <stdbool.h> true false |
true false |
falsehoods |
0 0.0 NULL false | false |
logical operators |
&& || ! | && || ! |
relational operators |
== != < > <= >= | == != < > <= >= |
integer type | signed char 1+ bytes short int 2+ bytes int 2+ bytes long int 4+ bytes long long int 4+ bytes types with portable sizes are defined in stdint.h: int8_t int16_t int32_t int64_t |
int int8 int16 int32 int64 |
unsigned type | unsigned char: 1+ bytes unsigned short int 2 bytes+ unsigned int 2 bytes+ unsigned long int 4+ bytes unsigned long long int 4+ bytes types with portable sizes are defined in stdint.h: uint8_t uint16_t uint32_t uint64_t |
uint8 (byte) uint16 uint32 uint64 |
float type | float 4 bytes double 8 bytes long double 16 bytes registers may be larger on some systems |
float32 float64 |
arithmetic operators |
+ - * / % | + - * / % |
integer division |
3 / 7 | 3 / 7 |
integer division by zero |
system dependent; process often sent a SIGFPE signal | on Unix, process sent a SIGFPE signal |
float division |
3 / (float)7 | 3 / float32(7) |
float division by zero | /* these are float values but not literals: */ inf, nan, or -inf |
// these are float values but not literals: +Inf, NaN, or -Inf // to get the float values: import "math" math.Inf(1) math.Nan() math.Inf(-1) |
power | #include <math.h> pow(2.0, 3.0) |
import "math" math.Pow(2.0, 3.0) |
sqrt | #include <math.h> sqrt(2); |
include "math" math.Sqrt(2) |
sqrt -1 | #include <math.h> /* nan */ double x = sqrt(-1.0); |
import "math" // NaN x := math.Sqrt(-2.0) import "math/cmplx" // (0+1.41421356i) z := cmplx.Sqrt(-2.0) |
transcendental functions | #include <math.h> exp log log2 log10 sin cos tan asin acos atan atan2 |
include "math" math.Exp math.Log math.Log2 math.Log10 math.Sin math.Cos math.Tan math.Asin math.Acos math.Atan math.Atan2 |
transcendental constants | #include <math.h> M_PI M_E |
import "math" math.Pi Math.E |
float truncation | #include <math.h> double d = 3.77; long trunc = (long)d; long rnd = round(d); long flr = floorl(d); long cl = ceill(d); |
include "math" x = 3.77 trunc := int(x) none flr := int(math.Floor(x)) cl := int(math.Ceil(x)) |
absolute value | #include <math.h> /* fabs() */ int i = abs(-7); float x = fabs(-7.77); |
include "math" none math.Abs(-7.77) |
complex type | float complex 8 bytes double complex 16 bytes long double complex 32 bytes |
complex64 complex128 |
complex construction | #include <complex.h> double complex z; z = 1.0 + 2.0 * I; /* C11: */ double complex z = CMPLX(1.0, 2.0); |
var z complex128 = 1.0 + 2.0i |
complex decomposition real and imaginary component, argument, absolute value, conjugate |
#include <complex.h> double x; double complex w; x = creal(z); x = cimag(z); x = carg(z); x = cabs(z); w = conj(z); |
import "math/cmplx" var x float64 var w complex128 x = real(z) x = imag(z) x = cmplx.Phase(z) x = cmplx.Abs(z) w = cmplx.Conj(z) |
random number uniform integer, uniform float |
/* lrand48 returns value in [0, 2**31 - 1]: */ long n = lrand48(() % 100; /* Value in interval [0.0, 1.0): */ double x = drand48(); |
import "math/rand" n := rand.Intn(100) x := rand.Float64() |
random seed | srand48(17); | import "math/rand" rand.Seed(17) |
bit operators |
<< >> & | ^ ~ | << >> & | none ^ |
strings | ||
c | go | |
string type |
char * wchar_t * wchar_t is typically 32 bits on Linux and 16 bits on Windows. |
string |
string literal |
/* string in initialized data segment: */ char *s = "hello"; wchar_t *ws = L"hello"; /* string in heap: */ char *s2 = strdup(s); wchar_t *ws2 = wcsdup(ws); /* if strdup cannot allocate memory, it returns NULL and sets errno to ENOMEM. */ |
"hello" // raw string literal: `hello` |
newline in string literal | /* compiler concatenates literals separated by whitespace: */ char *s = "first line\n" "second line"; |
// backquote literals only: let s := `first line second line` |
string escapes | \a \b \f \n \r \t \v \" \' \? \\ \o \oo \ooo \xhh \uhhhh \Uhhhhhhhh |
Do |