很多程序员都是从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 |
Double quote literals only: \a \b \f \n \r \t \v \\ \" \ooo \xhh \uhhhh \Uhhhhhhhh |
| < | ||

这篇博客针对从C/C++转向Go语言的程序员,强调在学习Go时需要注意与C/C++的差异。通过对比学习,可以更好地理解和掌握Go的特性。文章引用了Hyperpolyglot的资源,提供了一个并排的语言参考表,涵盖了语法、变量、数组、字典、并发等多个方面的对比。
916

被折叠的 条评论
为什么被折叠?



