从C/C++到Go

       很多程序员都是从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 | directoriesprocesses 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
 
C11gcc 4.8clang 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
expression interpolation none  
compare strings /* == and < compare memory addresses: */

strcmp("hello", "world") == 0
strcmp("hello", "world") < 0

wcscmp(L"hello", L"world") == 0
wcscmp(L"hello", L"world") < 0
"hello" == "world"
"hello" < "world"
string to number /* conversion functions:
    strtol strtoll
    strtoul strtoull
    strtof strtod strtold */
#include <limits.h>

char *s = "101 dalmations";
char *rest;
long n = strtol(s, &rest, 10);

if (n == 0 && errno == EINVAL)
  printf("invalid input\n");
else if ((n == LONG_MAX || n == LONG_MIN) && errno == ERANGE)
  printf("overflow\n");
else
  printf("%ld %s\n", n, rest);

/* wide string conversion functions:
    wcstol wcstoll
    wcstoul wcstoull
    wcstof wcstod wcstold */
import "strconv"

//2nd arg is base, 3rd arg is size of int in bits:
i, _ := strconv.ParseInt("17", 10, 32)

// 2nd arg is size of float in bits:
x, _ := strconv.ParseFloat("3.14", 32)
number to string long n = 1234;

char buf[100];
snprintf(buf, 100, "%ld", n);

wchar_t buf2[100];
swprintf(buf2, 100, L"%ld", n);

/* some format specifiers:
    %d %ld %lld
    %u %lu %llu
    %.3f %.3e */
import "strconv"

//3rd arg is precision after decimal point;
// 4th arg is size of float in bits:
strconv.FormatFloat(3.14, 'f', 4, 32)

// 2nd arg is base:
strconv.FormatInt(7, 10)
split /* strtok_r modifies 1st arg */
char *s = strdup("foo,bar baz");
char *sep = " ,";
char *tok, *last;

/* tok is never an empty string: */
for (tok = strtok_r(s, sep, &last);
     tok;
     tok = strtok_r(NULL, sep, &last))
  printf("token: %s\n", tok);

/* also wcstok */
import "strings"

s := "foo bar baz"
parts := strings.Split(s, " ")
join
 
none import "strings"

parts := []string{"foo", "bar", "baz"}
s := strings.Join(parts, " ")
concatenate char *s1 = "hello";
char *s2 = " world";
size_t len = strlen(s1) + strlen(s2) + 1;
char *s3 = (char *)calloc(len, sizeof *s3);

strcpy(s3, s1);
strcat(s3, s2);

/* also wcscpy and wcscat */
"hello" + " world"
replicate none import "strings"

hbar := strings.Repeat("-", 80)
extract substring char target[3];
char *source = "hello";

strncpy(target, source + 2, 2);
target[2] = '\0';

/* also wcsncpy */
"hello"[2:4]
index of substring const char *s = "hello";
const char *p = strstr("hello", "ll");
size_t idx = p ? p - s : -1;

/* also wcsstr */
import "strings"

// zero-based index; -1 if not found:
strings.Index("hello", "ll")
format string char buf[100];
snprintf(buf, 100, "%s: %d", "Spain", 7);

wchar_t buf2[100];
swprintf(buf2, 100, L"%S: %d", L"Spain", 7);
 
translate case

to upper, to lower
char *s = strdup("hello");
int i;

for (i=0; i < strlen(s); ++i)
  s[i] = toupper(s[i]);

for (i=0; i < strlen(s); i++)
  s[i] = tolower(s[i]);

/* also towupper and towlower */
import "strings"

strings.ToUpper("hello")
strings.ToLower("HELLO")
trim
both sides, on left, on right
char *s = strdup(" lorem ");
size_t i, j;

/* trim left */
for (i = 0; s[i] && isspace(s[i]); ++i);
if (i)
  for (size_t j = 0; j < strlen(s) - i + 1; ++j)
    s[j] = s[j + i];

/* trim right */
for (i = strlen(s) - 1; s[i] && isspace(s[i]); —i);
s[i + 1] = '\0';

/* also iswspace */
import "strings"

s := " lorem "
strings.Trim(s, " ")
strings.TrimLeft(s, " ")
strings.TrimRight(s, " ")
pad char buf[100];

/* pad right: */
snprintf(buf, 100, "%-10s", "hello");
/* pad left: */
snprintf(buf, 100, "%10s", "hello");

/* also swprintf */
 
length
 
strlen("hello")
wcslen(L"hello")
len("hello")
character type char
wchar_t
rune
character literal 'A'
L'A'
 
character lookup "lorem ipsum"[6]
L"lorem ipsum"[6]
 
character index char *s = "aaa bbb ccc";
char *p;
size_t n;

p = strchr(s, ' ');
if (p)
  printf("first space at %ld\n", p - s);
p = strrchr(s, ' ');
if (p)
  printf("last space at %ld\n", p - s);

n = strspn(s, "abc");
printf("first %ld chars in set\n", n);
p = strpbrk(s, " ,:.");
printf("first %ld chars not in set\n", n);

/* also: wcschr wcsrchr wcsspn wcspbrk */
 
character tests #include <ctype.h>
#include <wctype.h>

isascii
isrune
iscntrl
isgraph
isalpha
isspace
isupper
islower
isalnum
isdigit
isxdigit
ispunct

/* also: iswascii, iswrune, ... */
 
chr and ord /* Character types are integer types so no conversion is necessary. Use %c and %C to print a character like a string of length one. */
char ch = 'A';
wchar_t ch2 = L'A';

int i = ch + 7;
int i2 = ch2 + 7;

wprintf(L"%c %d %C %d\n", ch, ch, ch2, ch2);
 
regular expressions
  c go
metacharacters /* REG_BASIC: */
. [ ] \ * ^ $

/* REG_EXTENDED: */
. [ ] \ ( ) * + ? { } | ^ $
. [ ] \ ( ) * + ? { } | ^ $

use raw string (i.e. backtick) literals to avoid having to escape backslashes.
character class abbrevations /* matches any character; does not match newline if
   REG_NEWLINE is used: */
.

/* more character classes available in pcre library */
. \d \D \s \S \w \W
anchors /* match beginning and end of string; match beginning and
   end of line if REG_NEWLINE is used: */
^ $
^ $ \A \b \B \z
match test #include <regex.h>

regex_t rx;
int retval;
char *pat = "1999";
char *s = "It's 1999";

/* Use REG_NOSUB if 4th arg to regexec() is NULL */
if (retval = regcomp(&rx, pat, REG_EXTENDED | REG_NOSUB)) {
  char buf[200];
  regerror(retval, &rx, buf, 200);
  fprintf(stderr, "regex error: %s\n", buf);
} else {
  if (regexec(&rx, s, 0, NULL, 0) == 0)
    printf("Party!\n");
  regfree(&rx);
}
import "regexp"

var rx = regexp.MustCompile("1999")
if (rx.MatchString("It's 1999.")) {
  fmt.Println("Party!")
}
case insensitive match test #include <regex.h>

regex_t rx;
int retval;
char *pat = "lorem";
char *s = "Lorem";

if (retval = regcomp(&rx, pat, REG_EXTENDED | REG_ICASE)) {
  char buf[200];
  regerror(retval, &rx, buf, 200);
  fprintf(stderr, "Regex error: %s\n", buf);
} else {
  if (regexec(&rx, s, 0, NULL, 0) == 0)
    printf("case insensitive match\n");
  regfree(&rx);
}
import "regexp"

var rx = regexp.MustCompile("(?i)lorem")
if (rx.MatchString("Lorem Ipsum")) {
  fmt.Println("case insensitive match")
}
modifiers /* bit flags used in 3rd arg of regcomp(): */
REG_BASIC
REG_EXTENDED
REG_ICASE
REG_NOSUB
REG_NEWLINE
// use (?i), (?m), ... to insert in regex:
i m s U
substitution   import "regexp"

s := "do re mi mi mi"
var rx = regexp.MustCompile("mi")
fmt.Println(rx.ReplaceAllString(s, "ma"))
group capture #include <regex.h>

regex_t rx;
int retval;
char *pat = "([0-9]{4})-([0-9]{2})-([0-9]{2})";
char *s = "2010-06-03";

if (retval = regcomp(&rx, pat, REG_EXTENDED)) {
  char buf[200];
  regerror(retval, &rx, buf, 200);
  fprintf(stderr, "Regex error: %s\n", buf);
} else {
  /* first match is entire pattern */
  regmatch_t matches[4];
  if (regexec(&rx, s, 4, matches, 0) == 0) {
    char yr[5];
    regmatch_t rm = matches[1];
    /* rm_so and rm_eo contain index of start and end of
       match; they are set to -1 if unused */
    strncpy(yr, s + rm.rm_so, rm.rm_eo - rm.rm_so);
    yr[5] = '\0';
    printf("year is %s\n", yr);
  }
  regfree(&rx);
}
 
dates and time
  c go
unix epoch type
 
time_t int64
broken-down datetime type struct tm Time
current unix epoch time_t now;

if (time(&now) == -1)
  perror("time failed");
import "time"

t := time.Now().Unix()
current datetime   import "time"

dt := time.Now()
broken-down datetime to unix epoch /* use host local time as tz: */
time_t t = mktime(&dt);

/* use UTC as tz: */
time_t t2 = timegm(&dt2);
t := dt.Unix()
unix epoch to broken-down datetime struct tm dt, dt2;

if (!localtime_r(&now, &dt))
  perror("localtime_r failed");

/* UTC: */
if (!gmtime_r(&now, &dt2))
  perror("gmtime_r failed");
var t int64 = 1421929926
var ns int64 = 0
dt := time.Unix(t, ns)
format datetime char buf[100];
char *fmt = "%Y-%m-%d %H:%M:%S";

if (!strftime(buf, 100, fmt, &dt))
  fputs("strftime failed\n", stderr);
layout := "2006-01-02 15:04:05"

fmt.Println(dt.Format(layout))
parse datetime char *s = "1999-09-10 23:30:00";
char *fmt = "%Y-%m-%d %H:%M:%S";
char *p = strptime(s, fmt, &dt3);
if (!p)
  fputs("strptime failed\n", stderr);
layout := "2006-01-02:15:04:05"

dt, err := time.Parse(layout, "1999-09-10 23:30:00")
date subtraction /* use mktime for local; timegm for utc: */
double delta_sec = difftime(mktime(&dt), mktime(&dt2));
var delta time.Duration

delta = dt.Sub(dt2)
add duration dt.tm_sec += 1000;
mktime(&dt);

dt.tm_hour += 1000;
mktime(&dt);

dt.tm_mday += 1000;
mktime(&dt);
dt2 := dt + 1000 * time.Second
dt3 := dt + 1000 * time.Hour
date parts int yr = dt.tm_year + 1900;
int mo = dt.tm_mon + 1;
int dy = dt.tm_mday;
yr := dt.Year()
var mo time.Month = dt2.Month()
dy := dt.Day()
time parts int hr = dt.tm_hour;
int mi = dt.tm_min;
int ss = dt.tm_sec;
hr := dt.Hour()
mi := dt.Minute()
ss := dt.Second()
build broken-down datetime dt.tm_year = 1999 - 1900;
dt.tm_mon = 9 - 1;
dt.tm_mday = 10;
dt.tm_hour = 23;
dt.tm_min = 30;
dt.tm_sec = 0;
dt.tm_isdst = 1;
dt.tm_gmtoff = -7 * 60 * 60;

if (mktime(&dt) == -1)
  fputs("mktime failed\n", stderr);
import "time"

yr := 1999
var mo time.Month = 9
dy, hr, mi, ss, ns := 10, 23, 30, 0, 0
loc, _ := time.LoadLocation("Local")

dt := time.Date(yr, mo, dy, hr, mi, ss, ns, loc)
local time zone determination On a Unix system, the local time zone is stored in /etc/localtime. A process can have a different local time zone by setting the TZ environment variable.  
time zone info
name and utc offset in hours
offset abbreviation:
dt.tm_zone

UTC offset in hours:
dt.tm_gmtoff / 3600.0
name, offset_sec := dt.Zone()

offset abbreviation:
name

UTC offset in hours:
offset_sec / 3600.0
daylight savings test
 
dt.tm_isdst  
microseconds #include <sys/time.h>

struct timeval t;

if (gettimeofday(&t, NULL) == -1)
  perror("gettimeofday failed");
else
  printf("epoch: %lu usec: %u\n", t.tv_sec, t.tv_usec);
dt.Nanosecond() / 1000
fixed-length arrays
  c go
declare int a[10]; // values are zero-initialized:
var a [10]int
allocate on stack /* contents of memory undefined: */
int a[10];
compiler decides location in memory
allocate on heap #include <stdlib.h>

/* memory zero-initialized: */
int *a = calloc(10, sizeof *a);
compiler decides location in memory
free heap
 
free(a); none; garbage collected
literal
 
int a[] = {1, 2, 3}; a := []int{1, 2, 3}
size
 
  len(a)
lookup
 
a[0] a[0]
update
 
a[0] = 4; a[0] = 4
out-of-bounds behavior undefined, possible SIGSEGV panic: index out of range

if compiler detects a problem the code won't compile
element index char *a[3] = {"foo", "bar", "baz"};
int loc = -1, i;

for (i = 0; i < 3; ++i) {
  if (strcmp("bar", a[i]) == 0) {
    loc = i;
    break;
  }
}
a := []string{"foo", "bar", "baz"}
loc := -1

for i, val := range a {
  if val == "bar" {
    loc = i
  }
}
slice int *a2;

a2 = a[2];
a := []string{"a", "b", "c", "d", "e"}

// {"c", "d"}:
a2 := a[2:4]
slice to end   a := []string{"a", "b", "c", "d", "e"}

// {"c", "d", "e"}:
a2 := a[2:]
concatenate   a := []int{1, 2, 3}
a2 := []int{4, 5, 6}
a3 := append(a, a2...)
copy   a := []int{1, 2, 3}

a2 := a
// also sets a[0] to 4:
a2[0] = 4

a3 := make([]int, len(a))
copy(a3, a)
// a[0] is unchanged:
a3[0] = 5
iterate over elements int a[10];

for (i = 0; i < 10; ++i ) {
  a[i] = i * i;
}
 
iterate over indices and elements    
reverse   import "sort"

a := []int{1, 2, 3}
sort.Sort(sort.Reverse(sort.IntSlice(a)))
sort int
compare(const void *a, const void *b) {
  if (*(int *)a < *(int *)b) {
    return -1;
  }
    else if (*(int *)a == *(int *)b) {
    return 0;
  }
  else {
    return 1;
  }
}

int a[5] = {6, 8, 10, 9, 7};

/* 2nd arg is array length; 3rd arg is element size */
qsort(a, 5, sizeof (int), &compare);
 
resizable arrays
  c go
declare   // slice of length 5; capacity 10:
a := make([]int, 5, 10)
literal   a := []int{1, 2, 3}
size
 
  len(a)

// number of elements that can be stored in allocated memory;
// runtime reallocates when needed:
cap(a)
lookup
 
  a[0]
update
 
  a[0] = 4
out-of-bounds behavior   panic: index out of range

if compiler detects a problem the code won't compile
element index   a := []string{"foo", "bar", "baz"}
loc := -1

for i, val := range a {
  if val == "bar" {
    loc = i
  }
}
slice   a := []string{"a", "b", "c", "d", "e"}

// {"c", "d"}:
a2 := a[2:4]
slice to end   a := []string{"a", "b", "c", "d", "e"}

// {"c", "d", "e"}:
a2 := a[2:]
manipulate back   a := []int{1, 2, 3}

a = append(a, 4)
num := a[len(a) - 1]
a = a[:len(a) - 1]
manipulate front    
concatenate   a := []int{1, 2, 3}
a2 := []int{4, 5, 6}
a3 := append(a, a2...)
copy   a := []int{1, 2, 3}

a2 := a
// also sets a[0] to 4:
a2[0] = 4

a3 := make([]int, len(a))
copy(a3, a)
// a[0] is unchanged:
a3[0] = 5
iterate over elements   a := []string{"do", "re", "mi"}
for _, s := range(a) {
  fmt.Printf("value: %s\n", s)
}
iterate over indices and elements   a := []string{"do", "re", "mi"}
for i, s := range(a) {
  fmt.Printf("value at %d: %s\n", i, s)
}
reverse   import "sort"

a := []int{1, 2, 3}
sort.Sort(sort.Reverse(sort.IntSlice(a)))
sort    
map   none
filter   none
reduce   none
dictionaries
  c go
declare
 
  d := make(map[string]int)
literal
 
  d := map[string]int {"t": 1, "f": 0}
size
 
  len(d)
lookup
 
  d["t"]
update
 
  d["t"] = 2
missing key behavior
 
  returns zero value for value type
is key present   // If key not present, val will contain
// zero value for type and ok will contain false:
val, ok = d["y"]]
delete
 
  delete(d, "f")
iterate   for k, v := range d {
  fmt.Printf("%s: %d\n", k, v)
}
keys and values as arrays    
functions
  c go
define function int add(int n, int m) {
  return n + m;
}
func add(n int, m int) int {
  return n + m
}

// parameters can share type declaration:
func add(n, m int) int {
  return n + m
}
invoke function
 
add(3, 7) add(3, 7)
forward declaration of function float add(float x, float y);

/* if a function invocation is encountered before a
  declaration or a definition, the arguments and the
  return value are assumed to have type 'int' */
printf("%f\n", add(2.2, 3.5));

float add(float x, float y) {
  return x + y;
}
// function can be invoked before definition
fmt.Printf("%f\n", add(2.2, 3.5))

func add(n float32, m float32) float32 {
  return n + m
}
overload function not permitted not permitted
nest function not permitted not permitted
default value for parameter none none
variable number of arguments #include <stdarg.h>

char* concat(int cnt, ...) {

  int i, len;
  va_list ap;
  char *retval, *arg;

  va_start(ap, cnt);
  for (i = 0, len = 0; i < cnt; i++) {
    len += strlen(va_arg(ap, char*));
  }
  va_end(ap);

  retval = calloc(len + 1, sizeof *retval);

  va_start(ap, cnt);
  for (i = 0, len = 0; i < cnt; i++) {
    arg = va_arg(ap, char*);
    strcpy(retval + len, arg);
    len += strlen(arg);
  }
  va_end(ap);

  return retval;
}

char *s = concat(4, "Hello", ", ", "World", "!");
func concat(strs ...string) string {
  var ret = ""
  for _, str := range strs {
    ret += str
  }

  return ret
}
named parameters none none
pass by value void use_integer(int i) {
  function body
}

int i = 7;

use_integer(i);
 
pass by address void use_iptr(int *i) {
  function body
}

int i = 7;

use_iptr(&i);
 
pass by reference not possible  
return value return arg return arg. If return values have names and no arguments are provided to return the values assigned to the return variables are used.
no return value /* declare function void: */
void print_err(char *msg) {
  fprintf(stderr, msg);
}
 
multiple return values not permitted func divmod(m, n int) (int, int) {
  return m / n, m % n
}

q, r := divmod(7, 3)
named return values none func divmod(m, n int) (q, r int) {
  q = m / n
  r = m % n
  return
}

q, r := divmod(7, 3)
execute on return   import "os"

// prints "x is 7"
func x_is_7() {
  x := 7
  defer fmt.Println(x)
  x = 8
  defer os.Stdout.WriteString("x is ")
}
anonymous function literal none  
invoke anonymous function    
function with private state int
counter() {
  static int n = 0;

  return ++n;
}
 
function as value int
add(int m, int n) {
  return m + n;
}

/* a function cannot be stored in a variable, but
  its address can */
int (* fp)(int, int) = &add;

printf("1 + 2: %d\n", (*fp)(1, 2));
 
execution control
  c go
if int signum;

if (i > 0) {
  signum = 1;
} else if (i == 0) {
  signum = 0;
} else {
  signum = -1;
}
var signum int

if x > 0 {
  signum = 1
} else if x == 0 {
  signum = 0
} else {
  signum = -1
}
switch /* switch expression must be an integer */

switch (i) {
case 0:
case 1:
  printf("i is boolean\n");
  break;
default:
  printf("i is not a boolean\n");
  break;
}

/* use "break" to prevent falling through */
// switch expression can have any type

switch i {
case 0, 1:
  fmt.Println("i is boolean")
default:
  fmt.Println("i is not a boolean")
}

// use "fallthrough" to fall through
while int i = 0;

while (i < 10) {
  ++i;
}
i := 0

for i < 10 {
  i++
}
for int i, n;

for (i = 1, n = 1; i <= 10; ++i) {
  n *= i;
}
var i, n int

// Initialization and afterthought must be single
// statements; there is no comma operator.
n = 1
for i = 1; i <= 10; i++ {
  n *= i;
}
for with local scope none n := 1

for i := 1; i <= 10; i++ {
  n *= i;
}

// i is no longer in scope
infinite loop for (;;) {
  /* code */
}

while (1) {
  /* code */
}
for {
  // code
}
break
 
break break
break from nested loops use goto or flag variable   var a, b int

Outer:
  for a = 1; ; a++ {
    for b = 1; b < a; b++ {
      c := int(math.Sqrt(float64(a * a + b * b)))
      if c * c == a * a + b * b {
        break Outer
      }
    }
  }
continue
 
continue continue
single statement branches and loops while (n % 17 != 0)
  ++n;

if (n < 0)
  printf("negative\n");
// braces are mandatory:
if n < 0 {
  fmt.Println("negative")
}
dangling else int a = 1, b = -3, c;

/* indentation shows how ambiguity is resolved */
if (a > 0)
  if (b > 0)
    c = 1;
  else
    c = 2;

/* gcc warns about dangling else; -Werror turns warnings into errors */
no ambiguity
goto   if (err) {
    goto cleanup;
  }

  /* code */

cleanup:
  printf("cleaning up...\n");
  if err {
    goto Cleanup
  }

  // code

Cleanup:
  fmt.Println("cleaning up...")
longjump #include <setjmp.h>

void
callee(jmp_buf env) {
  longjmp(env, 1);
  /* unreachable */
}

void
caller() {
  jmp_buf env;

  switch (setjmp(env)) {
  case 0:
    callee(env);
    /* unreachable */
    break;
  case 1:
    printf("returned from callee\n");
    break;
  default:
    printf("unexpected setjump value\n");
  }
}
none
finally block    
concurrency
  c go
sleep #include <unistd.h>

/* seconds */
int retval = sleep(10);
if (retval != 0) {
  printf("interupted with %d s to go", retval);
}

/* microseconds */
if (usleep(10000)) {
  perror("usleep failed");
}
dur := time.Duration(10 * time.Second)
time.Sleep(dur)

dur2 := time.Duration(10000 * time.Microsecond)
time.Sleep(dur2)
timeout    
start thread #include <pthread.h>

typedef struct {
  int id;
} payload;

void*
thread(void* arg) {
  payload* pl = (payload*)arg;
  printf("the value is %d\n", pl->id);
}

pthread_t thr;
payload pl = {3};

if (pthread_create(&thr, NULL, &thread, (void*)&pl)) {
  printf("failed to create thead\n");
  exit(1);
}
 
terminate current thread #include <pthread.h>

payload pl = {7};

pthread_exit((void*)&pl);
 
terminate other thread #include <pthread>

pthread_t thr;
payload pl = {3};

if (pthread_create(&thr, NULL, &thread, (void*)&pl)) {
  printf("failed to create thead\n");
  exit(1);
}

sleep(5);

if (pthread_cancel(thr)) {
  printf("failed to cancel thread\n");
  exit (1);
}
 
list threads no portable way  
wait on thread    
lock    
create message queue    
send message    
receive message    
file handles
  c go
standard file handles stdin stdout stderr import "os"

os.Stdin os.Stdout os.Stderr
read line from stdin char *line = NULL;
size_t cap = 0;
ssize_t len;

/* if line is not NULL, it should be memory allocated by
   malloc and the size should be in cap. If size is not
   sufficient getline will call realloc on line */
len = getline(&line, &cap, stdin);

if (len == -1) {
  if (ferror(stdin)) {
    perror("getline err");
  }
  else if (feof(stdin)) {
    fprintf(stderr, "end of file\n");
  }
} else {

  /* use line here */

  free(line);
}
import "bufio"
import "os"

var line string
var err error

b := bufio.NewReader(os.Stdin)

line, err = b.ReadString('\n')

if err != nil {
  os.Stderr.WriteString("error!")
} else {
  // use line here
}
write line to stdout /* returns EOF on error */
int retval = puts("Hello, World!");
import "os"

os.Stdout.WriteString("Hello, World!\n")
write formatted string to stdout
 
printf("count: %d\n", 7);
wprintf(L"count: %d\n", 7);
fmt.Printf("count: %d\n", 7)
open file for reading /* returns NULL on error */
FILE *f = fopen("/etc/hosts", "r");
raw, err := os.Open("/etc/hosts")
if err == nil {
  f := bufio.NewReader(f)
}
open file for writing /* returns NULL on error */
FILE *f = fopen("/tmp/test", "w");
 
open file for appending /* returns NULL on error */
FILE *f = fopen("/tmp/err.log", "a");
 
close file /* returns EOF on error */
int retval = fclose(f);
 
close file implicitly none defer
i/o errors Functions return values such as EOF, NULL, or -1 to indicate error. Some functions return the value of errno. In some cases errors are not distinguished from end-of-file. The functionsferror() and feof() can be used to test a file handle.

The type of error is stored in
 errno. strerror(errno) or the thread safe strerror_r(errno, buf, buflen) convert the errors code to a string and perror() writes its argument to stderr withsterror(errno).
 
read line char line[BUFSIZ];

if (fgets(line, BUFSIZ, f) == NULL) {
  if (ferror(stdin)) {
    perror("getline err");
  }
  else if (feof(stdin)) {
    fprintf(stderr, "end of file\n");
  }

} else {
  if ('\n' == line[strlen(line) - 1]) {

    /* use line here */

} else {
    fprintf(stderr, "long line truncated\n");
}
 
iterate over file by line    
read file into array of strings    
read file into string    
write string /* returns EOF on error */
int retval = fputs("Hello, World!", f);
 
write line /* returns EOF on error */
int retval = fputs("Hello, World!\n", f);
 
flush file handle if (fflush(f) == EOF) {
  perror("fflush failed");
}
 
end-of-file test
 
feof(f)  
get and set file handle position long pos;
if ((pos = ftell(f)) == -1) {
  perror("ftell failed");
}

/* 3rd arg can also be SEEK_CUR or SEEK_END */
if (fseek(f, 0, SEEK_SET) == -1) {
  perror("fseek failed");
}
 
open unused file #include <limits.h>  /* PATH_MAX */
#include <unistd.h>

char buf[PATH_MAX];

strcpy(buf, "/tmp/foo.XXXXXX");

/* terminal Xs will be replaced: */
int fd = mkstemp(buf);

if (fd != -1) {
  FILE *f = fdopen(fd, "w");

  if (NULL == f) {
    perror("fdopen failed");
  } else {
    /* use f */
  }

} else {
  perror("mkstemp failed");
}
 
files
  c go
file test, regular file test
 
#include <sys/stat.h>
#include <unistd.h>  /* access() */

struct stat buf;

if (access("/tmp/foo", F_OK) >= 0) {
  /* file exists */
}

if (stat("/tmp/foo", &buf) != 0) {
  perror("stat failed");
} else if (S_ISREG(buf.st_mode)) {
  /* file is regular */
}
import "os"

fi, err := os.Stat("/tmp/foo")
if os.IsNotExist(err) {
  fmt.Printf("Does not exit\n")
} else {
  fmt.Printf("Exists\n")
  fm := fi.Mode()
  if fm.IsRegular() {
    fmt.Printf("Is Regular")
  } else {
    fmt.Printf("Is Not Regular")
  }
}
file size
 
#include <sys/stat.h>

struct stat buf;

if (stat("/tmp/foo", &buf) != 0) {
  perror("stat failed");
} else {
  printf("size: %llu\n", buf.st_size);
}
fi.Size()
is file readable, writable, executable #include <unistd.h>

if (access("/etc/hosts", R_OK) != 0) {
  printf("not readable\n");
}
if (access("/etc/hosts", W_OK) != 0) {
  printf("not writable\n");
}
if (access("/etc/hosts", X_OK) != 0) {
  printf("not executable\n");
}
 
set file permissions #include <sys/stat.h>

if (chmod("/tmp/foo", 0755) == -1) {
  perror("chmod failed");
}
import "os"

err := os.Chmod("/tmp/foo", 0755)
if err != nil {
  fmt.Printf("Chmod failed\n")
}
last modification time    
copy file, remove file, rename file /* no copy function in standard library */

if (remove("/tmp/foo")) {
  perror("remove failed");
}

if (rename("/tmp/bar", "/tmp/foo")) {
  perror("rename failed");
}
import "os"

// no copy function in standard library

err := os.Remove("/tmp/foo")
if err != nil {
  fmt.Printf("Remove failed: %s\n", err)
}

err2 := os.Rename("/tmp/bar", "/tmp/foo")
if err2 != nil {
  fmt.Printf("Rename failed: %s\n", err2)
}
create symlink, symlink test, readlink #include <limits.h>  /* PATH_MAX */
#include <sys/stat.h>
#include <unistd.h>

if (symlink("/etc/hosts", "/tmp/hosts") == -1) {
  perror("symlink failed");
}

struct stat sbuf;

if (stat("/tmp/hosts", &buf) != 0) {
  perror("stat failed");
} else if (S_ISLNK(buf.st_mode)) {
  /* file is symlink */
}

char pbuf[PATH_MAX + 1];

ssize_t size = readlink("/tmp/hosts", pbuf, PATH_MAX);

if (size >= 0 ) {
  pbuf[size] = 0;
  /* pbuf now contains null-terminated string
     with target path */
}
import "os"

err := os.Symlink("/etc/hosts", "/tmp/hosts")
if err != nil {
  fmt.Printf("Symlink failed: %s\n", err)
}

fi, err2 := os.Lstat("/tmp/hosts")
if err2 == nil {
  fm := fi.Mode()
  if fm & os.ModeSymlink != 0 {
    fmt.Println("File is a Symlink")
  }
} else {
  fmt.Printf("Lstat failed: %s\n", err2)
}

s, err3 := os.Readlink("/tmp/hosts")
if err3 != nil {
  fmt.Printf("Readlink failed: %s\n", err3)
} else {
  fmt.Printf("Link target: %s\n", s)
}
generate unused file name /* if first argument is NULL, path is in system temp
   directory. Caller should free() return value. */
char *path = tempnam("/tmp", "foo");
import "io/ioutil"

// Uses system tmp dir if 1st arg is empty string:
f, err := ioutil.TempFile("/tmp", "foo")
if err == nil {
  fmt.Printf("writing to: %s\n", f.Name())
  f.WriteString("foo content")
}
directories
  c go
working directory   import "os"

dir, err := os.Getwd()
if err != nil {
  os.Stderr.WriteString("Gtwd failed\n")
} else {
  fmt.Printf("pwd: %s\n", dir)
}

err2 := os.Chdir("/tmp")
if err2 != nil {
  os.Stderr.WriteString("Chdir failed\n");
}
build pathname   import "path"

pathname := path.Join("/etc", "hosts")
fmt.Printf("path: %s\n", pathname)
dirname and basename #include <libgen.h>

char *s1 = strdup("/etc/hosts");
char *s2 = strdup("/etc/hosts");
/* Check whether s1 or s2 are NULL. */

/* Some implementations return pointers to statically allocated
   memory which is overwritten by subsequent calls;
   others modify the input string. */
char *s3 = dirname(s1);
char *s4 = basename(s2);
import "path"

path.Dir("/etc/hosts")
path.Base("/etc/hosts")
absolute pathname char *s;

if ((s = realpath("..", NULL)) == NULL) {
  perror("realpath failed");
}
else {
  /* use s */
}
 
iterate over directory by file #include <dirent.h>

DIR *dir = opendir("/etc");
struct dirent *de;

while (de = readdir(dir)) {
  printf("%s\n", de->d_name);
}

closedir(dir);
import "io/ioutil"

a, err := ioutil.ReadDir("/etc")
if err == nil {
  for _, fi := range a {
    fmt.Printf("name: %s\n", fi.Name())
  }
}
glob paths #include <glob.h>

glob_t pglob;
int i;

glob("/etc/*", 0, NULL, &pglob);

for (i = 0; i < pglob.gl_pathc; ++i) {
  printf("%s\n", pglob.gl_pathv[i]);
}

globfree(&pglob);
import "path/filepath"

a, err := filepath.Glob("/etc/*")
if err == nil {
  for _, path := range(a) {
    fmt.Printf("path: %s\n", path)
  }
}
make directory #include <sys/stat.h>

if (mkdir("/tmp/foo")) {
  fprintf(stderr, "mkdir err: %s\n", strerror(errno));
}
err := os.Mkdir("/tmp/foo", 0775)
if err != nil {
  fmt.Printf("Mkdir failed: %s\n", err)
}
recursive copy    
remove empty directory #include <unistd.h>

if (rmdir("/tmp/foo") == -1) {
  perror("rmdir failed");
}
err := os.Remove("/tmp/foo")
if err != nil {
  fmt.Printf("Remove failed: %s", err)
}
remove directory and contents   err := os.RemoveAll("/tmp/foo")
if err != nil {
  fmt.Printf("RemoveAll failed: %s", err)
}
directory test
 
#include <sys/stat.h>

struct stat buf;

if (stat("/tmp/foo", &buf) != 0) {
  perror("stat failed");
} else if (S_ISDIR(buf.st_mode)) {
  /* file is directory */
}
 
generate unused directory #include <limits.h>

char buf[PATH_MAX];

strcpy(buf, "/tmp/fooXXXXXX");

/* terminal Xs will be replaced: */
if (mkdtemp(buf) == NULL) {
  perror("mkdtemp failed");
} else {
  /* use buf */
}
import "io/ioutil"

// Uses system tmp dir if 1st arg is empty string:
path, err := ioutil.TempDir("/tmp", "foo")
if err == nil {
  fmt.Printf("dir path: %s\n", path)
}
system temporary file directory /* defined in <stdio.h> */
P_tmpdir
import "os"

path := os.TempDir()
processes and environment
  c go
command line arguments int main(int argc, char **argv) {
  if (argc > 1)
    printf("first arg: %s\n", argv[1]);
  return 0;
}
import "os"

if len(os.Args) > 1 {
  fmt.Printf("first arg: %\n", os.Args[1])
}
program name int main(int argc, char **argv) {
  printf("program name: %s\n", argv[0]);
  return 0;
}
import "os"

fmt.Printf("program name: %s\n", os.Args[0])
environment variable #include <stdlib.h>

char *home = getenv("HOME");
setenv("EDITOR", "emacs", 1);
unsetenv("EDITOR");
import "os"

home := os.Getenv("HOME")

err := os.Setenv("EDITOR", "emacs")
if err != nil {
  fmt.Printf("Setenv failed: %s\n", err)
}
iterate over environment variables extern char **environ;
char **env, *p, *key;

for (env = environ; *env; ++env) {
  p = strchr(*env, '=');
  if (p) {
    size_t keylen = p - *env;
    key = strndup(*env, keylen);
    printf("key: %s value: %s\n", key, *env + keylen + 1);
    free(key);
  }
}
import "os"
import "strings"

for _, s := range os.Environ() {
  a := strings.SplitN(s, "=", 2)
  fmt.Printf("key: %s value: %s\n", a[0], a[1])
}
get user id and name #include <unistd.h>  /* getlogin */

printf("uid: %d\n", getuid());
printf("username: %s\n", getlogin());
import "os"

os.Getuid()
/* username? */
exit /* use 0 for success; 1 through 127 for failure */
exit(1);
import "os"

os.Exit(1)
executable test #include <unistd.h>

if (access("/bin/ls", X_OK) != 0) {
  printf("not executable\n");
}
 
external command /* retval of -1 indicates fork or wait failed.
   127 indicates shell failed */
int retval = system("ls -l *");
 
fork    
exec    
pipe    
wait    
get pid, parent pid #include <unistd.h>

/* getpid() and getppid() have return type pid_t */
printf("%d\n", getpid());
printf("%d\n", getppid())
import "os"

fmt.Println(os.Getpid())
fmt.Println(os.Getppid())
set signal handler #include <signal.h>

/* assumes a POSIX environment */
void
handle_signal(int signo) {
  int restore = errno;
  switch(signo) {
  case SIGUSR1:
    write(1, "caught SIGUSR1\n", 15);
    break;
  default:
    break;
  }
  errno = restore;
}

/* 2nd arg can also be SIG_IGN or SIG_DFL */
sig_t prev_handler = signal(SIGUSR1, &handle_signal);

if (prev_handler == SIG_ERR) {
  perror("signal failed");
  exit(1);
}
 
send signal #include <signal.h>
#include <unistd.h>  /* getppid */

if (kill(getppid(), SIGUSR1) == -1) {
  perror("kill failed");
}
 
option parsing
  c go
getopt #include <getopt.h>

/* 2nd value indicates whether option takes an argument */
static struct option long_opts[] = {
  {"debug", no_argument, NULL, 'd'},
  {"threshold", required_argument, NULL, 't'},
  {0, 0, 0, 0}
};

int debug = 0;
double threshold = 0.0;
char *file = NULL;

int ch;
int opti;
char *endptr;

while (1) {
  ch = getopt_long(argc, argv, "dt:", long_opts, &opti);
  if (-1 == ch) {
    break;
  }

  switch (ch) {
  case 'd':
    debug = 1;
    break;
  case 't':
    threshold = strtod(optarg, &endptr);
    if (*endptr != 0) {
      fprintf(stderr, "expected float: %s\n", optarg);
      exit(1);
    }
    break;
  default:
    fprintf(stderr, "unexpected arg: %d\n", ch);
    exit(1);
  }
}

/* optind is index of 1st arg not consumed by getopt */
if (optind != argc - 1) {
  fputs("USAGE: foo [--multi] [--threshold=NUM] FILE\n",
        stderr);
  exit(1);
}
else {
  file = argv[optind];
}
 
libraries and namespaces
  c go
load library /* The library must also be linked:

     $ gcc foo.o main.c

   If the library is in an archive:

     $ gcc -lfoo main.c
*/
#include "foo.h"
import "foo"

// Only capitalized identifiers are visible:
var bar = foo.GetBar()
load library in subdirectory #include "lib/foo.h" import "lib/foo"
library path Add directory to path searched by #include directive:
$ gcc -I/home/fred/include foo.c

Add directory to path searched by -l (lowercase L) option:
$ gcc -L/home/fred/lib -lbar foo.c
The installation libraries are in the GOROOT directory. Additional directories can be listed in the GOPATH environment variable. The directories are separated by colons (semicolons) on Unix (Windows).

Each directory contains a
 src subdirectory containing source code and a pkg/ARCH subdirectory containing compiled libraries.
declare namespace none // A package declaration must be first statement
// in every source file..
package foo
alias namespace
 
none import fu "foo"
unqualified import of namespace none import . "foo"
unqualified import of definitions    
package manager
search, install, list installed
   
user-defined types
  c go
typedef typedef int customer_id;
customer_id cid = 3;
 
enum enum day_of_week {
  mon, tue, wed, thu, fri, sat, sun
};

enum day_of_week dow = tue;
 
struct definition struct medal_count {
  const char* country;
  int gold;
  int silver;
  int bronze;
};
type MedalCount struct {
  country string
  gold int
  silver int
  bronze int
}
struct declaration
 
struct medal_count spain;  
struct initialization struct medal_count spain = {"Spain", 3, 7, 4};

struct medal_count france = {
  .gold = 8,
  .silver = 7,
  .bronze = 9,
  .country = "France"
};
spain := MedalCount{"Spain", 3, 2, 1}

france := MedalCount{
  bronze: 9,
  silver: 7,
  gold: 8,
  country: "France"}
struct literal struct medal_count france;

france = (struct medal_count) {
  .gold = 8,
  .silver = 7,
  .bronze = 9,
  .country = "France"
};
 
struct member assignment spain.country = "Spain";
spain.gold = 3;
spain.silver = 7;
spain.bronze = 4;
france := MedalCount{}
france.country = "France"
france.gold = 7
france.silver = 6
france.bronze = 5
struct member access int spain_total = spain.gold + spain.silver + spain.bronze; france_total = france.gold +
  france.silver +
  france.bronze
c preprocessor macros
  c go
include file /* search path include system directories: */
#include <stdio.h>

/* search path also includes directory of source file */
#include "foo.h"
 
add system directory $ gcc -I/opt/local/include foo.c  
define macro #define PI 3.14  
command line macro $ gcc -DPI=3.14 foo.c  
undefine macro #undef PI  
macro with arguments #define MIN(X, Y) ((X) < (Y) ? (X) : (Y))  
stringify macro argument    
concatenate tokens    
conditional compilation #if defined __WIN32
  win32_prinft("%f\n", x);
#else
  printf("%f\n", x);
#endif
 
macro operators The conditional of #if can contain integer literals and the following operators:

&& || !
== != < > <= >=
+ - * / %
<< >> & | ^ ~

In addition, the defined() operator can be used to test whether a macro is defined.

#ifdef FOO is a shortcut for #if defined(FOO)
 
net and web
  c go
http get   import "io/ioutil"
import "net/http"

resp, err := http.Get("http://www.google.com")
if err == nil {
  defer resp.Body.Close()
  body, err := ioutil.ReadAll(resp.Body)
  if err == nil {
    fmt.Println(string(body))
  }
}
unit tests
  c go
unit test example $ sudo apt-get install check

$ cat > check_foo.c
#include <check.h>

START_TEST(test_foo) {
  fail_unless(0, "not true");
}
END_TEST

Suite *
suite_foo(void) {
  Suite *ste = suite_create("suite: foo");
  TCase *tc = tcase_create("case: foo");

  tcase_add_test(tc, test_foo);
  suite_add_tcase(ste, tc);

  return ste;
}

int
main(void) {
  int number_failed;
  Suite *ste = suite_foo();
  SRunner *sr = srunner_create(ste);

  srunner_run_all(sr, CK_NORMAL);
  number_failed = srunner_ntests_failed(sr);
  srunner_free(sr);

  return (number_failed);
}

$ gcc -o check_foo check_foo.c -lcheck

$ ./check_foo
Running suite(s): foo
0%: Checks: 1, Failures: 1, Errors: 0
check_foo.c:4:F:foo:test_foo:0: not equal
 
equality assertion fail_unless(1 == 2, "integers not equal");

char *s = "lorem";
fail_unless(strcmp(s, "ipsum"), "strings not equal");
 
setup and teardown    
unit test coverage    
debugging and profiling
  c go
check syntax $ gcc -fsyntax-only foo.c  
flag for stronger warnings $ gcc -Wall foo.c  
suppress warnings $ gcc -w foo.c  
treat warnings as errors $ gcc -Werror foo.c  
lint $ sudo apt-get install splint
$ splint foo.c
 
source cleanup    
run debugger $ gcc -g -o foo foo.c
$ gdb foo
 
debugger commands
help, list source, (re)load executable, next, step, set breakpoint, show breakpoints, delete breakpoint, continue, backtrace, up stack, down stack, print, run, quit
> h
> l [FIRST_LINENO, LAST_LINENO]
> file PATH
> n
> s
> b [FILE:]LINENO
> i
> d NUM
> c
> bt
> up
> do
> p EXPR
> r [ARG1[, [ARG2 ...]]
> q
 
cpu usage #include <sys/times.h>
#include <unistd.h>  /* sysconf */

struct tms start, end;

double ticks_per_s = (double)sysconf(_SC_CLK_TCK);

clock_t start_wall = times(&start);

if (start_wall < 0) {
  fputs("times failed", stderr);
  return (1);
}

int i;
for (i = 0; i < 1000 * 1000 * 1000; ++i) {
  /* empty loop */
}

clock_t end_wall = times(&end);

if (end_wall < 0) {
  fputs("times failed", stderr);
  return (1);
}

clock_t wall = end_wall - start_wall;
clock_t user = end.tms_utime - start.tms_utime;
clock_t system = end.tms_stime - start.tms_stime;

printf("wall: %f s\n", wall / ticks_per_s);
printf("user: %f s\n", user / ticks_per_s);
printf("system: %f s\n", system / ticks_per_s);
 
profile code does not work on Mac OS X
$ gcc -pg -o foo foo.c
$ ./foo
$ gprof foo
 
memory tool $ sudo apt-get install valgrind
$ gcc -o foo foo.c
$ valgrind foo
 
  _________________________________________________________________ _________________________________________________________________

       

猜你喜欢

转载自blog.csdn.net/stpeace/article/details/81370072