标签归档:Golang

Golang中空字符表示

空字符(Null character)又称结束符,缩写NUL,是一个数值为0的控制字符。在C语言中空字符用来表示字符串的结束。

在C语言中也可以直接插入空字符:


#include
int main(void)
{
puts("hello\0world");
}

但是在Go中,类似的代码是不行的:

package main
import "fmt"
func main(){
fmt.Println("hello\0world")
}
//print: /tmp/g.go:4: non-octal character in escape sequence: w

查看文档:https://golang.org/ref/spec#String_literals

修改一下即可:

package main
import "fmt"
func main(){
fmt.Println("hello\000world")
}

Golang多版本共存方案

如果你是一个狂热的Golang爱好者,也许你会同时使用两个或两个以上的Golang版本。那么这时候怎么实现呢?

这里提供一个Russ cox的方案。这个方案是在Google Group里看到的,但是我现在已经找不到具体是哪个链接了。


#file:/usr/bin/go1.4
#!/bin/bash
export GOROOT=$HOME/go1.4
export PATH=$HOME/go1.4/bin:$PATH
exec $GOROOT/bin/go "$@"

历史稳定版本可以这样处理,然后把开发版本作为默认的。

all done.

另:Russ cox 已经成为我的偶像啦

分享自己用Golang写的一个Web bench 工具

最近一直在学习Golang,业余时间开了个Web bench 工具awb,awb是another web bench的缩写,基本功能已完成,兼容ab的参数。

初步测试并发性比ab要好一些。感觉Golang除了在服务端开发方面有很大的优势以外,在写各类工具方面也是挺方便顺手的。估计未来会有很多写的运维工具使用Golang 编写。

总体上来说Go非常符合我的胃口。既有PHP的简洁、高效,在性能、并发、异步方面又有很好的系统级别的支持。整体上很有当年第一次看到PHP的时候的感觉。。。心动不已啊 🙂

项目地址:https://github.com/tomheng/awb

[转]How does the Go runtime work?

(This answer is for the Go compiler from golang.org. It is not about gccgo.)

The Go runtime is a Go package, which appears (in the documentation, the build process, the things it exports) to be like any other Go package. It is written in a combination of Go, C, and assembly. In order for it to do all the low level things it needs to do, there are special adaptations (hacks?) in the build system and in the compiler that are activated when compiling it. The runtime has architecture- and OS-specific things in it, which are compiled in according the the target platform.

At linking time, the linker creates a statically linked ELF (or PE or MachO) file which includes the runtime, your program, and every package that your program references. The starting address in the ELF header points into the runtime. It arranges for it’s own data structures to be initialized, then calls the initializers of all the packages (ordering of init is probably figured out at link time by the linker). It then transfers control to main.main, and your program is running. (There are situations where Go creates dynamically linked executables, but the majority of the code is still statically linked.)

When your program does things that could cause a crash, like a cast, or accessing an item in an array, the compiler emits calls into the runtime, which checks the data type with run time type info, or checks the bounds of the array. Likewise for memory allocation and for creating new goroutines, the runtime gets control. The runtime has a user-space scheduler in it, which implements cooperative multitasking; if a goroutine goes into a tight loop without calling any routines that would block (thereby giving the scheduler control) it can starve all the other goroutines. The runtime spawns a new system thread when needed to prevent the system from blocking on system calls. There can be fewer system threads in a Go system than the number of goroutines that are active.

The final aspect of the Go runtime that is very interesting is the per-goroutine stack. The runtime, together with the linker, arranges for the hardware stack to be non-contiguous, able to grow and shrink according to demand. As the stack shrinks after growing, it is freed and is available to be realloced as other types of objects by the memory allocator. This allows Go stacks to start very small (8 k), meaning that a Go program can launch hundreds of thousands of Goroutines without running out of address space. (The stack is becoming continuous in Go 1.5 but it can still be reallocated and moved when it runs out.)

When programming Go, the runtime is not in the front of your mind. You interact with the system library, and the runtime supports your code more or less silently. This is why the majority of information you’ll see about Go is how to use the libraries and how to use the channels to implement concurrent programming, and little about the runtime itself.

原文:http://www.quora.com/How-does-the-Go-runtime-work

Golang 使用心得-正确关闭channel

相信很多同学都是因为Golang有相当简单的并发模型才转过来的。Golang的并发模型主要由三部分构成:Goroutine、Channel和Select。

其中Channel是Goroutine之间通信的桥梁,简单优雅的解决了并行开发中的同步问题。

但是初学者(比如我)通常会遇到 send on closed channel的错误,这是因为我们向一个已经关闭channle推送数据造成的。通常这个错误是发生在生成消费模型中。channel用来传送需要执行的任务,channel一端是生产者,另一端是消费者。

如下代码:

package main

import (
"fmt"
"sync"
)

func main() {
jobs := make(chan int)
var wg sync.WaitGroup
wg.Add(10)
go func() {
for i := 0; i < 10; i++ { jobs <- i fmt.Println("produce:", i) } }() go func() { for i := range jobs { fmt.Println("consume:", i) wg.Done() } }() wg.Wait() }

注意上面的代码我们没有主动关闭channel,因为我一开始就知道执行的任务数,所以直接等待任务完成即可,没有必要主动关闭channel。

假设我们的场景中,生产者没有生成数量的限制,只有一个时间限制。那么代码演变成下面这样:

package main

import (
"fmt"
"sync"
"time"
)

func main() {
jobs := make(chan int)
var wg sync.WaitGroup
go func() {
time.Sleep(time.Second * 3)
close(jobs)
}()
go func() {
for i := 0; ; i++ {
jobs <- i fmt.Println("produce:", i) } }() wg.Add(1) go func() { defer wg.Done() for i := range jobs { fmt.Println("consume:", i) } }() wg.Wait() }

这时程序就会因为send on closed channel而崩溃。那么首先想到的解决方案可能是在放入jobs的时候检查jobs是否已关闭。幸好Golang有办法来检测channel是否被关闭,但是非常不好用。Golang中可以用comma ok的方式检测channel是否关闭,如下:

i, ok := <- jobs 如果channel关闭那么ok返回的是false,但是这样的话,如果jobs没有关闭,那么就会漏掉一个job。当然你可以想办好hack掉漏掉的这个job。但是这样的代码不是很优雅,也是那么直观合理。 在实践中我是用的如下代码处理这个问题。
package main

import (
"fmt"
"sync"
"time"
)

func main() {
jobs := make(chan int)
var wg sync.WaitGroup
timeout := make(chan bool)
go func() {
time.Sleep(time.Second * 3)
timeout <- true }() go func() { for i := 0; ; i++ { select { case <-timeout: close(jobs) return default: jobs <- i fmt.Println("produce:", i) } } }() wg.Add(1) go func() { defer wg.Done() for i := range jobs { fmt.Println("consume:", i) } }() wg.Wait() }

实际情况可能还要复杂很多,比如会有多个生产者,这个时候代码又该如何处理呢?大家可以想一想。。。

[转]Go Data Structures

When explaining Go to new programmers, I’ve found that it often helps to explain what Go values look like in memory, to build the right intuition about which operations are expensive and which are not. This post is about basic types, structs, arrays, and slices.

Basic types

Let’s start with some simple examples:

godata1

The variable i has type int, represented in memory as a single 32-bit word. (All these pictures show a 32-bit memory layout; in the current implementations, only the pointer gets bigger on a 64-bit machine—int is still 32 bits—though an implementation could choose to use 64 bits instead.)

The variable j has type int32, because of the explicit conversion. Even though i and j have the same memory layout, they have different types: the assignment i = j is a type error and must be written with an explicit conversion: i = int(j).

The variable f has type float, which the current implementations represent as a 32-bit floating-point value. It has the same memory footprint as the int32 but a different internal layout.

Structs and pointers

Now things start to pick up. The variable bytes has type [5]byte, an array of 5 bytes. Its memory representation is just those 5 bytes, one after the other, like a C array. Similarly, primesis an array of 4 ints.

Go, like C but unlike Java, gives the programmer control over what is and is not a pointer. For example, this type definition:

type Point struct { X, Y int }

defines a simple struct type named Point, represented as two adjacent ints in memory.

godata1a

The composite literal syntax Point{10, 20} denotes an initialized Point. Taking the address of a composite literal denotes a pointer to a freshly allocated and initialized Point. The former is two words in memory; the latter is a pointer to two words in memory.

Fields in a struct are laid out side by side in memory.

type Rect1 struct { Min, Max Point }
type Rect2 struct { Min, Max *Point }

godata1b

Rect1, a struct with two Point fields, is represented by two Points—four ints—in a row. Rect2, a struct with two *Point fields, is represented by two *Points.

Programmers who have used C probably won’t be surprised by the distinction between Point fields and *Point fields, while programmers who have only used Java or Python (or …) may be surprised by having to make the decision. By giving the programmer control over basic memory layout, Go provides the ability to control the total size of a given collection of data structures, the number of allocations, and the memory access patterns, all of which are important for building systems that perform well.

Strings

With those preliminaries, we can move on to more interesting data types.

godata2

(The gray arrows denote pointers that are present in the implementation but not directly visible in programs.)

A string is represented in memory as a 2-word structure containing a pointer to the string data and a length. Because the string is immutable, it is safe for multiple strings to share the same storage, so slicing s results in a new 2-word structure with a potentially different pointer and length that still refers to the same byte sequence. This means that slicing can be done without allocation or copying, making string slices as efficient as passing around explicit indexes.

(As an aside, there is a well-known gotcha in Java and other languages that when you slice a string to save a small piece, the reference to the original keeps the entire original string in memory even though only a small amount is still needed. Go has this gotcha too. The alternative, which we tried and rejected, is to make string slicing so expensive—an allocation and a copy—that most programs avoid it.)

Slices

godata3

A slice is a reference to a section of an array. In memory, it is a 3-word structure contaning a pointer to the first element, the length of the slice, and the capacity. The length is the upper bound for indexing operations like x[i] while the capacity is the upper bound for slice operations like x[i:j].

Like slicing a string, slicing an array does not make a copy: it only creates a new structure holding a different pointer, length, and capacity. In the example, evaluating the composite literal[]int{2, 3, 5, 7, 11} creates a new array containing the five values and then sets the fields of the slice x to describe that array. The slice expression x[1:3] does not allocate more data: it just writes the fields of a new slice structure to refer to the same backing store. In the example, the length is 2—y[0] and y[1] are the only valid indexes—but the capacity is 4—y[0:4] is a valid slice expression. (See Effective Go for more about length and capacity and how slices are used.)

Because slices are multiword structures, not pointers, the slicing operation does not need to allocate memory, not even for the slice header, which can usually be kept on the stack. This representation makes slices about as cheap to use as passing around explicit pointer and length pairs in C. Go originally represented a slice as a pointer to the structure shown above, but doing so meant that every slice operation allocated a new memory object. Even with a fast allocator, that creates a lot of unnecessary work for the garbage collector, and we found that, as was the case with strings above, programs avoided slicing operations in favor of passing explicit indices. Removing the indirection and the allocation made slices cheap enough to avoid passing explicit indices in most cases.

New and Make

Go has two data structure creation functions: new and make. The distinction is a common early point of confusion but seems to quickly become natural. The basic distinction is thatnew(T) returns a *T, a pointer that Go programs can dereference implicitly (the black pointers in the diagrams), while make(T, args) returns an ordinary T, not a pointer. Often that T has inside it some implicit pointers (the gray pointers in the diagrams). New returns a pointer to zeroed memory, while make returns a complex structure.

godata4

There is a way to unify these two, but it would be a significant break from the C and C++ tradition: define make(*T) to return a pointer to a newly allocated T, so that the currentnew(Point) would be written make(*Point). We tried this for a few days but decided it was too different from what people expected of an allocation function.

Coming soon…

This has already gotten a bit long. Interface values, maps, and channels will have to wait for future posts.

原文:http://research.swtch.com/godata