以下摘自The Go Programming Language:
Package names themselves are always in lower case.
package
名字总是小写字母。
以下摘自The Go Programming Language:
Package names themselves are always in lower case.
package
名字总是小写字母。
Go
语言中http package
包含Handle
和HandleFunc
两个函数:
func Handle
func Handle(pattern string, handler Handler)
Handle registers the handler for the given pattern in the DefaultServeMux. The documentation for ServeMux explains how patterns are matched.
func HandleFunc
func HandleFunc(pattern string, handler func(ResponseWriter, *Request))
HandleFunc registers the handler function for the given pattern in the DefaultServeMux. The documentation for ServeMux explains how patterns are matched.
Handle
函数的handler
参数是个interface
:
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
而HandleFunc
的handler
参数就是一个原型为func(ResponseWriter, *Request)
的函数。
参考下例(使用Handle
):
package main
import (
"net/http"
"log"
)
type httpServer struct {
}
func (server httpServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(r.URL.Path))
}
func main() {
var server httpServer
http.Handle("/", server)
log.Fatal(http.ListenAndServe("localhost:9000", nil))
}
使用HandleFunc
:
package main
import (
"net/http"
"log"
)
func main() {
http.HandleFunc("/", func (w http.ResponseWriter, r *http.Request){
w.Write([]byte(r.URL.Path))
})
log.Fatal(http.ListenAndServe("localhost:9000", nil))
}
根据The Go Programming Language:
A handler pattern that ends with a slash matches any URL that has the pattern as a prefix. Behind the scenes, the server runs the handler for each incoming request in a separate goroutine so that it can serve multiple requests simultaneously.
因此,如果http.Handle
和http.HandleFunc
所指定的handle pattern
是“/
”,则匹配所有的pattern
;而“/foo/
”则会匹配所有“/foo/*
”。
kubectl
实际运行的函数(k8s.io/kubernetes/pkg/kubectl/app/kubectl.go
):
func Run() error {
cmd := cmd.NewKubectlCommand(cmdutil.NewFactory(nil), os.Stdin, os.Stdout, os.Stderr)
return cmd.Execute()
}
NewKubectlCommand
的代码(k8s.io/kubernetes/pkg/kubectl/cmd/cmd.go
):
// NewKubectlCommand creates the `kubectl` command and its nested children.
func NewKubectlCommand(f *cmdutil.Factory, in io.Reader, out, err io.Writer) *cobra.Command {
// Parent command to which all subcommands are added.
cmds := &cobra.Command{
Use: "kubectl",
Short: "kubectl controls the Kubernetes cluster manager",
Long: `kubectl controls the Kubernetes cluster manager.
Find more information at https://github.com/kubernetes/kubernetes.`,
Run: runHelp,
BashCompletionFunction: bash_completion_func,
}
f.BindFlags(cmds.PersistentFlags())
// From this point and forward we get warnings on flags that contain "_" separators
cmds.SetGlobalNormalizationFunc(util.WarnWordSepNormalizeFunc)
cmds.AddCommand(NewCmdGet(f, out))
cmds.AddCommand(NewCmdDescribe(f, out))
cmds.AddCommand(NewCmdCreate(f, out))
......
return &cmds
}
所以cmd := cmd.NewKubectlCommand(cmdutil.NewFactory(nil), os.Stdin, os.Stdout, os.Stderr)
得到的cmd
是一个指向cobra.Command
的指针。
cmdutil.NewFactory
代码(k8s.io/kubernetes/pkg/kubectl/cmd/util/factory.go
):
// NewFactory creates a factory with the default Kubernetes resources defined
// if optionalClientConfig is nil, then flags will be bound to a new clientcmd.ClientConfig.
// if optionalClientConfig is not nil, then this factory will make use of it.
func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
mapper := kubectl.ShortcutExpander{RESTMapper: api.RESTMapper}
flags := pflag.NewFlagSet("", pflag.ContinueOnError)
flags.SetNormalizeFunc(util.WarnWordSepNormalizeFunc) // Warn for "_" flags
generators := map[string]kubectl.Generator{
"run/v1": kubectl.BasicReplicationController{},
"run-pod/v1": kubectl.BasicPod{},
"service/v1": kubectl.ServiceGeneratorV1{},
"service/v2": kubectl.ServiceGeneratorV2{},
"horizontalpodautoscaler/v1beta1": kubectl.HorizontalPodAutoscalerV1Beta1{},
"deployment/v1beta1": kubectl.DeploymentV1Beta1{},
"job/v1beta1": kubectl.JobV1Beta1{},
}
clientConfig := optionalClientConfig
if optionalClientConfig == nil {
clientConfig = DefaultClientConfig(flags)
}
clients := NewClientCache(clientConfig)
return &Factory{
......
}
因为cmdutil.NewFactory(nil)
参数为nil
,所以调用的是DefaultClientConfig
函数。
clientcmd.ClientConfig
定义在k8s.io/kubernetes/pkg/client/unversioned/clientcmd/client_config.go
文件:
// ClientConfig is used to make it easy to get an api server client
type ClientConfig interface {
// RawConfig returns the merged result of all overrides
RawConfig() (clientcmdapi.Config, error)
// ClientConfig returns a complete client config
ClientConfig() (*client.Config, error)
// Namespace returns the namespace resulting from the merged
// result of all overrides and a boolean indicating if it was
// overridden
Namespace() (string, bool, error)
}
DefaultClientConfig
代码(k8s.io/kubernetes/pkg/kubectl/cmd/util/factory.go
):
func DefaultClientConfig(flags *pflag.FlagSet) clientcmd.ClientConfig {
loadingRules := clientcmd.NewDefaultClientConfigLoadingRules()
flags.StringVar(&loadingRules.ExplicitPath, "kubeconfig", "", "Path to the kubeconfig file to use for CLI requests.")
overrides := &clientcmd.ConfigOverrides{}
flagNames := clientcmd.RecommendedConfigOverrideFlags("")
// short flagnames are disabled by default. These are here for compatibility with existing scripts
flagNames.ClusterOverrideFlags.APIServer.ShortName = "s"
clientcmd.BindOverrideFlags(overrides, flags, flagNames)
clientConfig := clientcmd.NewInteractiveDeferredLoadingClientConfig(loadingRules, overrides, os.Stdin)
return clientConfig
}
最后返回一个DeferredLoadingClientConfig
结构体(定义在k8s.io/kubernetes/pkg/client/unversioned/clientcmd/merged_client_builder.go
):
// DeferredLoadingClientConfig is a ClientConfig interface that is backed by a set of loading rules
// It is used in cases where the loading rules may change after you've instantiated them and you want to be sure that
// the most recent rules are used. This is useful in cases where you bind flags to loading rule parameters before
// the parse happens and you want your calling code to be ignorant of how the values are being mutated to avoid
// passing extraneous information down a call stack
type DeferredLoadingClientConfig struct {
loadingRules *ClientConfigLoadingRules
overrides *ConfigOverrides
fallbackReader io.Reader
}
以下摘自The Go Programming Language:
A const declaration gives names to constants, that is, values that are fixed at compile time. The value of a constant must be a number, string, or boolean.
const
的值只能是数字,字符串或者布尔值。
A constant declaration may specify a type as well as a value, but in the absence of an explicit type, the type is inferred from the expression on the right-hand side.
当定义常量时没有指定其类型时,常量的类型将由等号右边的表达式来决定。
下面是如何定义一组constant
:
When a sequence of constants is declared as a group, the right-hand side expression may be omitted for all but the first of the group, implying that the previous expression and its type should be used again. For example:
const (
a = 1
b
c = 2
d
)
fmt.Println(a, b, c, d) // “1 1 2 2”A const declaration may use the constant generator iota, which is used to create a sequence of related values without spelling out each one explicitly. In a const declaration, the value of iota begins at zero and increments by one for each item in the sequence. For example:
type Weekday int
const (
Sunday Weekday = iota
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
) This declares Sunday to be 0, Monday to be 1, and so on.
另外,关于untyped constants
的定义:
Constants in Go are a bit unusual. Although a constant can have any of the basic data types like int or float64, including named basic types like time.Duration, many constants are not committed to a particular type. The compiler represents these uncommitted constants with much greater numeric precision than values of basic types, and arithmetic on them is more precise than machine arithmetic; you may assume at least 256 bits of precision. There are six flavors of these uncommitted constants, called untyped boolean, untyped integer, untyped rune, untyped floating-point, untyped complex, and untyped string.
只有constant
才可能是untyped
,变量不可能是untyped
。
Only constants can be untyped. When an untyped constant is assigned to a variable, as in the first statement below, or appears on the right-hand side of a variable declaration with an explicit type, as in the other three statements, the constant is implicitly converted to the type of that variable if possible.
var f float64 = 3 + 0i // untyped complex -> float64
f = 2 // untyped integer -> float64
f = 1e123 // untyped floating-point -> float64
f = ‘a’ // untyped rune -> float64
The statements above are thus equivalent to these:
var f float64 = float64(3 + 0i)
f = float64(2)
f = float64(1e123)
f = float64(‘a’)
constant
之间转化要考虑是否有可能溢出:
Whether implicit or explicit, converting a constant from one type to another requires that the target type can represent the original value. Rounding is allowed for real and complex floating-point numbers:
const (
deadbeef = 0xdeadbeef // untyped int with value 3735928559
a = uint32(deadbeef) // uint32 with value 3735928559
b = float32(deadbeef) // float32 with value 3735928576 (rounded up)
c = float64(deadbeef) // float64 with value 3735928559 (exact)
d = int32(deadbeef) // compile error: constant overflows int32
e = float64(1e309) // compile error: constant overflows float64
f = uint(-1) // compile error: constant underflows uint )
要注意把untyped constant
赋值给变量时,变量类型的选择。
In a variable declaration without an explicit type (including short variable declarations), the flavor of the untyped constant implicitly determines the default type of the variable, as in these examples:
i := 0 // untyped integer; implicit int(0)
r := ‘\000’ // untyped rune; implicit rune(‘\000’)
f := 0.0 // untyped floating-point; implicit float64(0.0)
c := 0i // untyped complex; implicit complex128(0i)Note the asymmetry: untyped integers are converted to int, whose size is not guaranteed, but untyped floating-point and complex numbers are converted to the explicitly sized types float64 and complex128. The language has no unsized float and complex types analogous to unsized int, because it is very difficult to write correct numerical algorithms without knowing the size of one’s floating-point data types.
To give the variable a different type, we must explicitly convert the untyped constant to the desired type or state the desired type in the variable declaration, as in these examples:
var i = int8(0)
var i int8 = 0These defaults are particularly important when converting an untyped constant to an interface value since they determine its dynamic type.
fmt.Printf(“%T\n”, 0) // “int”
fmt.Printf(“%T\n”, 0.0) // “float64”
fmt.Printf(“%T\n”, 0i) // “complex128”
fmt.Printf(“%T\n”, ‘\000’) // “int32” (rune)
Node
(也称之为minion
)运行docker container
,而master
则负责调度管理这些container
。
Master
运行下列服务:
- API Server—nearly all the components on the master and nodes accomplish their respective tasks by making API calls. These are handled by the API Server running on the master.
- Etcd—Etcd is a service whose job is to keep and replicate the current configuration and run state of the cluster. It is implemented as a lightweight distributed key-value store and was developed inside the CoreOS project.
- Scheduler and Controller Manager—These processes schedule containers (actually, pods—but more on them later) onto target nodes. They also make sure that the correct numbers of these things are running at all times.
Node
运行下列进程:
- Kubelet—A special background process (daemon that runs on each node whose job is to respond to commands from the master to create, destroy, and monitor the containers on that host.
- Proxy—This is a simple network proxy that’s used to separate the IP address of a target container from the name of the service it provides.
- cAdvisor (optional)—http://bit.ly/1izYGLi[Container Advisor (cAdvisor)] is a special daemon that collects, aggregates, processes, and exports information about running containers. This information includes information about resource isolation, historical usage, and key network statistics.
A service is a process that:
1. is designed to do a small number of things (often just one).
2. has no user interface and is invoked solely via some kind of API.
An application, on the other hand, is pretty much the opposite of that. It has a user interface (even if it’s just a command line) and often performs lots of different tasks. It can also expose an API, but that’s just bonus points.
个人理解,service
一般专注做一件事,没有用户界面,并且通过API
与application
交互。而application
会有用户界面,并且通常可以运行很多任务。举个例子,web browser
就是application
,而web server
即为service
。
A Kubernetes cluster does not manage a fleet of applications. It manages a cluster of services.A service running in a container managed by Kubernetes is designed to do a very small number of discrete things.
If your services are small and of limited purpose, then they can more easily be scheduled and re-arranged as your load demands. Otherwise, the dependencies become too much to manage and either your scale or your stability suffers.
K8s
即是用来管理service
的。
kubectl
是控制k8s clustet manager
的命令行工具:
$ kubectl
kubectl controls the Kubernetes cluster manager.
Find more information at https://github.com/kubernetes/kubernetes.
Usage:
kubectl [flags]
kubectl [command]
Available Commands:
get Display one or many resources
describe Show details of a specific resource or group of resources
......
kubectl
使用了cobra这个项目作为构建命令行的工具,它包含commands
,args
和flags
的概念:
Commands represent actions, Args are things and Flags are modifiers for those actions.
The pattern to follow is APPNAME VERB NOUN --ADJECTIVE. or APPNAME COMMAND ARG --FLAG
举个例子:
$ kubectl get node --v=10
kubectl
是appname
,get
是command
,node
是arg
,--v=10
是flag
。
以下摘自The Go Programming Language:
The increment statement i++ adds 1 to i ; it’s equivalent to i += 1 which is in turn equivalent to i = i + 1 . There’s a corresponding decrement statement i– that subtracts 1. These are statements, not expressions as the y are in most languages in the C family, so j = i++ is illegal, and the y are postfix only, so –i is not legal either.
要注意,i++
和i--
在Go
语言中是语句,不是表达式,因此不能赋值给另外的变量。此外没有++i
和--i
。
以下摘自The Go Programming Language:
The import declarations must follow the package declaration.After that, a program consists of the declarations of functions, variables, constants, and types (introduced by the key words func, var , const , and type ); for the most part, the order of declarations does not matter.
import
语句必须跟在package
定义后面。请看下例:
package main
var str string = "Hello world!\n"
import "fmt"
func main(){
// your code goes
fmt.Println(str)
}
编译如下:
./prog.go:5: syntax error: unexpected import
调整一下语句位置:
package main
import "fmt"
var str string = "Hello world!\n"
func main(){
// your code goes
fmt.Println(str)
}
编译执行成功:
Hello world!
以下摘自The Go Programming Language:
Package main is special. It defines a standalone executable program, not a library. Within package main the function main is also special—it’s where execution of the program begins. Whatever main does is what the program does.
main package
不同于其它library package
,它定义了一个可执行程序。其中的main
函数即是可执行文件的入口函数。