當前位置: 首頁>>代碼示例>>Golang>>正文


Golang log.Error函數代碼示例

本文整理匯總了Golang中github.com/starkandwayne/rdpgd/log.Error函數的典型用法代碼示例。如果您正苦於以下問題:Golang Error函數的具體用法?Golang Error怎麽用?Golang Error使用的例子?那麽, 這裏精選的函數代碼示例或許可以為您提供幫助。


在下文中一共展示了Error函數的15個代碼示例,這些例子默認根據受歡迎程度排序。您可以為喜歡或者感覺有用的代碼點讚,您的評價將有助於係統推薦出更棒的Golang代碼示例。

示例1: BackupHandler

/* Should contain a form value dbname which equals the database name
   e.g. curl www.hostname.com/backup/now -X POST -d "dbname=nameofdatabase"
   The {how} should be either "now" or "enqueue" */
func BackupHandler(w http.ResponseWriter, request *http.Request) {
	vars := mux.Vars(request)
	dbname := request.FormValue("dbname")
	t := tasks.NewTask()
	t.Action = "BackupDatabase"
	t.Data = dbname
	t.Node = globals.MyIP
	t.Role = globals.ServiceRole
	t.TTL = 3600
	t.ClusterService = globals.ClusterService
	t.NodeType = "read"
	if rdpgconsul.IsWriteNode(globals.MyIP) {
		t.NodeType = "write"
	}

	var err error
	if dbname != "rdpg" {
		//Using FindByDatabase to determine if the database actually exists to be backed up.
		inst, err := instances.FindByDatabase(dbname)
		if err != nil {
			log.Error(fmt.Sprintf("admin.BackupHandler() instances.FindByDatabase(%s) Error occurred when searching for database.", dbname))
			w.WriteHeader(http.StatusInternalServerError)
			w.Write([]byte("Error encountered while searching for database"))
			return
		}
		if inst == nil {
			//...then the database doesn't exist on this cluster.
			log.Debug(fmt.Sprintf("admin.BackupHandler() Attempt to initiate backup on non-existant database with name: %s", dbname))
			w.WriteHeader(http.StatusNotFound)
			w.Write([]byte("Database not found"))
			return
		}
	}

	switch vars[`how`] {
	//Immediately calls Backup() and performs the backup
	case "now":
		err = t.BackupDatabase()
		if err != nil {
			log.Error(fmt.Sprintf(`api.BackupHandler() Task.BackupDatabase() %+v ! %s`, t, err))
			w.WriteHeader(http.StatusInternalServerError)
			w.Write([]byte("Error encountered while trying to perform backup"))
			return
		}
		w.Write([]byte("Backup completed."))
	case "enqueue":
		// Queues up a backup to be done with a worker thread gets around to it.
		// This call returns after the queuing process is done; not after the backup is done.
		err = t.Enqueue()
		if err != nil {
			log.Error(fmt.Sprintf(`api.BackupHandler() Task.Enqueue() %+v ! %s`, t, err))
			w.WriteHeader(http.StatusInternalServerError)
			w.Write([]byte("Error while trying to queue"))
			return
		}
		w.Write([]byte("Backup successfully queued."))
	default:
		w.WriteHeader(http.StatusNotFound)
	}
}
開發者ID:predix,項目名稱:rdpg-boshrelease,代碼行數:63,代碼來源:backup.go

示例2: getMasterIP

func getMasterIP(clusterName string) (masterIp string, err error) {

	log.Trace(fmt.Sprintf("gpb#consul.getMasterIP() Calling out to Consul at address %s", mcConsulIP))

	consulConfig := consulapi.DefaultConfig()
	consulConfig.Address = mcConsulIP
	consulClient, err := consulapi.NewClient(consulConfig)
	if err != nil {
		log.Error(fmt.Sprintf(`gpb#consul.getMasterIP() Consul IP: %s ! %s`, mcConsulIP, err))
		return
	}

	masterNode, _, err := consulClient.Catalog().Service(fmt.Sprintf(`%s-master`, clusterName), "", nil)
	if err != nil {
		log.Error(fmt.Sprintf("gpb#consul.getMasterIP() Cluster Name: %s ! %s", clusterName, err))
		return
	}

	if len(masterNode) == 0 {
		masterIp = "0.0.0.0"
		return masterIp, errors.New("Could not find the consul master ip")
	}

	masterIp = masterNode[0].Address
	log.Trace(fmt.Sprintf("gpb#consul.getMasterIP() Found master ip for %s = %s", clusterName, masterIp))
	return masterIp, err

}
開發者ID:predix,項目名稱:rdpg-boshrelease,代碼行數:28,代碼來源:consul.go

示例3: httpAuth

func httpAuth(h http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, request *http.Request) {
		if len(request.Header["Authorization"]) == 0 {
			log.Trace(fmt.Sprintf("httpAuth(): 'Authorization' Header Required"))
			http.Error(w, "Authorization Required", http.StatusUnauthorized)
			return
		}

		auth := strings.SplitN(request.Header["Authorization"][0], " ", 2)
		if len(auth) != 2 || auth[0] != "Basic" {
			log.Error(fmt.Sprintf("httpAuth(): Unhandled Authorization Type, Expected Basic"))
			http.Error(w, "Unhandled Authorization Type, Expected Basic\n", http.StatusBadRequest)
			return
		}
		payload, err := base64.StdEncoding.DecodeString(auth[1])
		if err != nil {
			log.Error(fmt.Sprintf("httpAuth(): Authorization base64.StdEncoding.DecodeString() Failed"))
			http.Error(w, "Authorization Failed\n", http.StatusUnauthorized)
			return
		}
		nv := strings.SplitN(string(payload), ":", 2)
		if (len(nv) != 2) || !isAuthorized(nv[0], nv[1]) {
			log.Error(fmt.Sprintf("httpAuth(): Authorization Failed: !isAuthorized() nv: %+v", nv))
			http.Error(w, "Authorization Failed\n", http.StatusUnauthorized)
			return
		}
		h(w, request)
	}
}
開發者ID:predix,項目名稱:rdpg-boshrelease,代碼行數:29,代碼來源:api.go

示例4: Register

// This is called on the management cluster when the service cluster has created
// a new database and is registering it's avialabilityh with the management cluster.
func (i *Instance) Register() (err error) {
	p := pg.NewPG(`127.0.0.1`, pbPort, `rdpg`, `rdpg`, pgPass)
	db, err := p.Connect()
	if err != nil {
		log.Error(fmt.Sprintf("instances.Register() p.Connect(%s) ! %s", p.URI, err))
		return err
	}
	defer db.Close()

	err = i.Lock()
	if err != nil {
		log.Error(fmt.Sprintf("instances.Instance#Register(%s) Failed Locking instance %s ! %s", i.Database, i.Database, err))
		return
	}
	sq := fmt.Sprintf(`INSERT INTO cfsb.instances (cluster_id,dbname, dbuser, dbpass,effective_at) VALUES ('%s','%s','%s','%s',CURRENT_TIMESTAMP)`, i.ClusterID, i.Database, i.User, i.Pass)
	log.Trace(fmt.Sprintf(`instances.Instance#Register(%s) > %s`, i.Database, sq))
	_, err = db.Exec(sq)
	if err != nil {
		log.Error(fmt.Sprintf("instances.Instance#Register(%s) ! %s", i.Database, err))
	}
	err = i.Unlock()
	if err != nil {
		log.Error(fmt.Sprintf(`instances.Instance#Register(%s) Unlocking ! %s`, i.InstanceID, err))
	}

	return
}
開發者ID:subhankarc,項目名稱:rdpg-boshrelease,代碼行數:29,代碼來源:register.go

示例5: MoveRemoteBackupFiles

func MoveRemoteBackupFiles(oldPath, newPath string) (err error) {
	log.Trace("tasks.MoveRemoteBackupFiles ! Beginning to move remote backup files")
	if !rdpgs3.Configured {
		errorMessage := "tasks.MoveRemoteBackupFiles !  s3 storage is not configured; exiting"
		log.Error(errorMessage)
		return errors.New(errorMessage)
	}
	//Helper functions rely on pointing to a specific place for globals.LocalBackupLocation...
	// so, I'm going to hack that for the duration of this function
	storedPath := globals.LocalBackupPath
	globals.LocalBackupPath = oldPath
	defer func() { globals.LocalBackupPath = storedPath }() //mmmm lambdas
	//Get all of the old files...
	backupList, err := RemoteListing("", true)
	if err != nil {
		log.Error(fmt.Sprintf("tasks.MoveRemoteBackupFiles ! backup.RemoteListing erred : %s", err.Error()))
		return err
	}
	//Move them over to the new location...
	err = moveS3(backupList, oldPath, newPath)
	if err != nil {
		log.Error(fmt.Sprintf("tasks.MoveRemoteBackupFiles ! tasks.moveS3 erred : %s", err.Error()))
		return err
	}
	return nil
}
開發者ID:predix,項目名稱:rdpg-boshrelease,代碼行數:26,代碼來源:upgrade.go

示例6: bdrBootstrap

func (r *RDPG) bdrBootstrap() (err error) {
	_, err = r.bootstrapLock()
	if err != nil {
		log.Error(fmt.Sprintf(`rdpg.RDPG<%s>#Bootstrap() r.bootstrapLock() ! %s`, ClusterID, err))
		return
	}

	leader := false
	key := fmt.Sprintf(`rdpg/%s/bdr/join/ip`, ClusterID)
	bdrJoinIP, err = r.getValue(key)
	if err != nil {
		log.Error(fmt.Sprintf(`rdpg.RDPG<%s>#Bootstrap() kv.getValue(%s) ! %s ...`, ClusterID, key, err))
		return err
	}
	if len(bdrJoinIP) == 0 || bdrJoinIP == globals.MyIP {
		log.Trace(fmt.Sprintf(`rdpg.RDPG<%s>#Bootstrap() kv.getValue(%s) BDR Join IP has not been set`, ClusterID, key))
		leader = true
	} else {
		log.Trace(fmt.Sprintf(`rdpg.RDPG<%s>#Bootstrap() kv.getValue(%s) BDR Join Node IP has been set to %s`, ClusterID, key, bdrJoinIP))
		leader = false
	}

	if leader {
		err = r.bdrLeaderBootstrap()
		if err != nil {
			log.Error(fmt.Sprintf(`rdpg.RDPG<%s>#Bootstrap() r.bdrLeaderBootstrap() ! %s`, ClusterID, err))
		}
	} else {
		err = r.bdrNonLeaderBootstrap()
		if err != nil {
			log.Error(fmt.Sprintf(`rdpg.RDPG<%s>#Bootstrap() r.bdrNonLeaderBootstrap() ! %s`, ClusterID, err))
		}
	}
	return
}
開發者ID:predix,項目名稱:rdpg-boshrelease,代碼行數:35,代碼來源:bootstrap.go

示例7: GetWriteMasterIP

/*
GetWriteMasterIP returns the write master IP for the service cluster.
*/
func (s *Service) GetWriteMasterIP() (ip string, err error) {
	log.Trace(fmt.Sprintf(`services.Service<%s>#GetWriteMaster()`, s.Name))
	client, err := consulapi.NewClient(consulapi.DefaultConfig())
	if err != nil {
		log.Error(fmt.Sprintf("services.Service<%s>#GetWriteMaster() ! %s", s.Name, err))
		return
	}
	catalog := client.Catalog()

	clusterID := os.Getenv("RDPGD_CLUSTER")
	if clusterID == "" {
		matrixName := os.Getenv(`RDPGD_MATRIX`)
		matrixNameSplit := strings.SplitAfterN(matrixName, `-`, -1)
		matrixColumn := os.Getenv(`RDPGD_MATRIX_COLUMN`)
		for i := 0; i < len(matrixNameSplit)-1; i++ {
			clusterID = clusterID + matrixNameSplit[i]
		}
		clusterID = clusterID + "c" + matrixColumn
	}
	svcs, _, err := catalog.Service(fmt.Sprintf(`%s-master`, clusterID), "", nil)

	if err != nil {
		log.Error(fmt.Sprintf(`services.Service<%s>#GetWriteMaster() ! %s`, s.Name, err))
		return
	}

	if len(svcs) == 0 {
		return "", nil
	}
	ip = svcs[0].Address
	return
}
開發者ID:predix,項目名稱:rdpg-boshrelease,代碼行數:35,代碼來源:services.go

示例8: DropDatabase

func (p *PG) DropDatabase(dbname string) (err error) {
	log.Trace(fmt.Sprintf(`pg.PG<%s>#DropDatabase(%s) Dropping postgres database...`, p.IP, dbname))
	p.Set(`database`, `postgres`)
	db, err := p.Connect()
	if err != nil {
		log.Error(fmt.Sprintf("pg.PG<%s>#DropDatabase(%s) ! %s", p.IP, dbname, err))
		return
	}
	defer db.Close()

	exists, err := p.DatabaseExists(dbname)
	if err != nil {
		log.Error(fmt.Sprintf("pg.PG<%s>#DropDatabase(%s) ! %s", p.IP, dbname, err))
		return
	}
	if !exists {
		log.Error(fmt.Sprintf("pg.PG<%s>#DropDatabase(%s) Database %s already does not exist.", p.IP, dbname, err))
		return
	}

	// TODO: How do we drop a database in bdr properly?
	sq := fmt.Sprintf(`DROP DATABASE IF EXISTS %s`, dbname)
	log.Trace(fmt.Sprintf(`pg.PG<%s>#DropDatabase(%s) > %s`, p.IP, dbname, sq))
	_, err = db.Exec(sq)
	if err != nil {
		log.Error(fmt.Sprintf("pg.PG<%s>#DropDatabase(%s) ! %s", p.IP, dbname, err))
		return
	}
	return
}
開發者ID:predix,項目名稱:rdpg-boshrelease,代碼行數:30,代碼來源:pg.go

示例9: DropUser

func (p *PG) DropUser(dbuser string) (err error) {
	log.Trace(fmt.Sprintf(`pg.PG<%s>#DropUser(%s) Dropping postgres user...`, p.IP, dbuser))
	p.Set(`database`, `postgres`)
	db, err := p.Connect()
	if err != nil {
		log.Error(fmt.Sprintf("pg.PG<%s>#DropUser(%s) %s ! %s", p.IP, dbuser, p.URI, err))
		return
	}
	defer db.Close()

	exists, err := p.UserExists(dbuser)
	if err != nil {
		log.Error(fmt.Sprintf("pg.PG<%s>#DropUser(%s) ! %s", p.IP, dbuser, err))
		return
	}
	if !exists {
		log.Error(fmt.Sprintf("pg.PG<%s>#DropUser(%s) User already does not exist, skipping.", p.IP, dbuser))
		return
	}
	// TODO: How do we drop a database in bdr properly?
	sq := fmt.Sprintf(`DROP USER %s`, dbuser)
	log.Trace(fmt.Sprintf(`pg.PG<%s>#DropDatabase(%s) > %s`, p.IP, dbuser, sq))
	_, err = db.Exec(sq)
	if err != nil {
		log.Error(fmt.Sprintf("pg.PG<%s>#DropDatabase(%s) ! %s", p.IP, dbuser, err))
		return
	}
	return
}
開發者ID:predix,項目名稱:rdpg-boshrelease,代碼行數:29,代碼來源:pg.go

示例10: CreateExtensions

// Create given extensions on a single target host.
func (p *PG) CreateExtensions(dbname string, exts []string) (err error) {
	log.Trace(fmt.Sprintf(`pg.PG<%s>#CreateExtensions(%s) Creating postgres extensions %+v on database...`, p.IP, dbname, exts))
	p.Set(`database`, dbname)
	db, err := p.Connect()
	if err != nil {
		log.Error(fmt.Sprintf("pg.PG<%s>#CreateExtensions(%s) %s ! %s", p.IP, dbname, p.URI, err))
		return
	}

	ddlLockRE := regexp.MustCompile(`cannot acquire DDL lock|Database is locked against DDL operations`)
	// TODO: Only create extension if it doesn't already exist.
	for _, ext := range exts {
		sq := fmt.Sprintf(`CREATE EXTENSION IF NOT EXISTS "%s";`, ext)
		log.Trace(fmt.Sprintf(`pg.PG<%s>#CreateExtensions() > %s`, p.IP, sq))
		for { // Retry loop for acquiring DDL schema lock.
			_, err = db.Exec(sq)
			if err != nil {
				if ddlLockRE.MatchString(err.Error()) {
					log.Trace("pg.PG#CreateExtensions() DDL Lock not available, waiting...")
					time.Sleep(1 * time.Second)
					continue
				}
				db.Close()
				log.Error(fmt.Sprintf("pg.PG<%s>#CreateExtensions() %s ! %s", p.IP, ext, err))
				return
			}
			break
		}
	}
	db.Close()
	return
}
開發者ID:predix,項目名稱:rdpg-boshrelease,代碼行數:33,代碼來源:pg.go

示例11: BDRDisableDatabase

// First break replication within the specified database
// Then disables the specific database from the postgres database
func (p *PG) BDRDisableDatabase(dbname string) (err error) {
	log.Trace(fmt.Sprintf(`pg.PG<%s>#BDRDisableDatabase(%s) Disabling postgres database...`, p.IP, dbname))
	p.Set(`database`, dbname)
	db, err := p.Connect()
	if err != nil {
		log.Error(fmt.Sprintf("pg.PG<%s>#BDRDisableDatabase(%s) %s ! %s", p.IP, dbname, p.URI, err))
		return
	}

	nodes := []string{}
	sq := `SELECT node_name FROM bdr.bdr_nodes;`
	err = db.Select(&nodes, sq)
	if err != nil {
		log.Error(fmt.Sprintf("pg.PG<%s>#BDRDisableDatabase(%s) %s ! %s", p.IP, dbname, sq, err))
	}
	for index, _ := range nodes {
		sq := fmt.Sprintf(`SELECT bdr.bdr_part_by_node_names(ARRAY['%s']);`, nodes[index])
		_, err = db.Exec(sq)
		if err != nil {
			log.Error(fmt.Sprintf("pg.PG<%s>#BDRDisableDatabase(%s) %s ! %s", p.IP, dbname, sq, err))
		}
	}
	db.Close()

	p.DisableDatabase(dbname) // Call the non-BDR disabling function.
	return
}
開發者ID:predix,項目名稱:rdpg-boshrelease,代碼行數:29,代碼來源:pg.go

示例12: GrantUserPrivileges

// Create a given user on a single target host.
func (p *PG) GrantUserPrivileges(dbuser string, priviliges []string) (err error) {
	log.Trace(fmt.Sprintf(`pg.PG<%s>#GrantUserPrivileges(%s) Granting postgres user priviliges %+v...`, p.IP, dbuser, priviliges))
	p.Set(`database`, `postgres`)
	db, err := p.Connect()
	if err != nil {
		log.Error(fmt.Sprintf("pg.PG<%s>#UserGrantPrivileges(%s) %s ! %s", p.IP, dbuser, p.URI, err))
		return
	}
	defer db.Close()

	for _, priv := range priviliges {
		sq := fmt.Sprintf(`ALTER USER %s WITH %s;`, dbuser, priv)
		log.Trace(fmt.Sprintf(`pg.PG<%s>#UserGrantPrivileges(%s) > %s`, p.IP, dbuser, sq))
		result, err := db.Exec(sq)
		rows, _ := result.RowsAffected()
		if rows > 0 {
			log.Trace(fmt.Sprintf(`pg.PG<%s>#CreateUser(%s) Successfully Created.`, p.IP, dbuser))
		}
		if err != nil {
			log.Error(fmt.Sprintf(`pg.PG<%s>#CreateUser(%s) ! %s`, p.IP, dbuser, err))
			return err
		}
	}
	return nil
}
開發者ID:predix,項目名稱:rdpg-boshrelease,代碼行數:26,代碼來源:pg.go

示例13: Find

func (b *Binding) Find() (err error) {
	log.Trace(fmt.Sprintf(`cfsb.Binding#Find(%s) ... `, b.BindingID))

	if b.BindingID == "" {
		return errors.New("Binding ID is empty, can not Binding#Find()")
	}
	p := pg.NewPG(`127.0.0.1`, pbPort, `rdpg`, `rdpg`, pgPass)
	db, err := p.Connect()
	if err != nil {
		log.Error(fmt.Sprintf("cfsb.Binding#Find(%s) ! %s", b.BindingID, err))
		return
	}
	defer db.Close()

	sq := fmt.Sprintf(`SELECT id,instance_id FROM cfsb.bindings WHERE binding_id=lower('%s') LIMIT 1`, b.BindingID)
	log.Trace(fmt.Sprintf(`cfsb.Binding#Find(%s) > %s`, b.BindingID, sq))
	err = db.Get(b, sq)
	if err != nil {
		if err == sql.ErrNoRows {
			log.Error(fmt.Sprintf("cfsb.Binding#Find(%s) ! Could not find binding with given Binding ID", b.BindingID))
		} else {
			log.Error(fmt.Sprintf("cfsb.Binding#Find(%s) ! %s", b.BindingID, err))
		}
	} else {
		// TODO: Load creds: b.Creds := Credentials{} ... b.Creds.Find()
	}
	return
}
開發者ID:predix,項目名稱:rdpg-boshrelease,代碼行數:28,代碼來源:bindings.go

示例14: Remove

func (b *Binding) Remove() (err error) {
	log.Trace(fmt.Sprintf(`cfsb.Binding#Remove(%s) ... `, b.BindingID))
	err = b.Find()
	if err != nil {
		log.Error(fmt.Sprintf(`cfsb.Binding#Remove(%s) ! %s`, b.BindingID, err))
		return
	}
	p := pg.NewPG(`127.0.0.1`, pbPort, `rdpg`, `rdpg`, pgPass)
	db, err := p.Connect()
	if err != nil {
		log.Error(fmt.Sprintf("cfsb.Binding#Remove(%s) ! %s", b.BindingID, err))
		return
	}
	defer db.Close()

	// TODO: Scheduled background task that does any cleanup necessary for an
	// unbinding (remove credentials?)
	sq := fmt.Sprintf(`UPDATE cfsb.bindings SET ineffective_at=CURRENT_TIMESTAMP WHERE binding_id=lower('%s')`, b.BindingID)
	log.Trace(fmt.Sprintf(`cfsb.Binding#Remove(%s) SQL > %s`, b.BindingID, sq))
	_, err = db.Exec(sq)
	if err != nil {
		log.Error(fmt.Sprintf(`cfsb.Binding#Remove(%s) ! %s`, b.BindingID, err))
	}

	b.Creds = &Credentials{
		InstanceID: b.InstanceID,
		BindingID:  b.BindingID,
	}

	err = b.Creds.Remove()
	if err != nil {
		log.Error(fmt.Sprintf(`cfsb.Binding#Remove(%s) b.Creds.Remove() ! %s`, b.BindingID, err))
	}
	return
}
開發者ID:predix,項目名稱:rdpg-boshrelease,代碼行數:35,代碼來源:bindings.go

示例15: serviceClusterCapacityStore

func (r *RDPG) serviceClusterCapacityStore() (err error) {
	if ClusterID == "rdpgmc" {
		return nil
	}
	instanceAllowed := os.Getenv(`RDPGD_INSTANCE_ALLOWED`)
	if instanceAllowed == "" {
		log.Error(fmt.Sprintf(`rdpg.RDPG<%s>#serviceClusterCapacityStore(): instanceAllowed is not configured or failed to export as environment variable! %s`, ClusterID))
	}
	instanceLimit := os.Getenv(`RDPGD_INSTANCE_LIMIT`)
	if instanceLimit == "" {
		log.Error(fmt.Sprintf(`rdpg.RDPG<%s>#serviceClusterCapacityStore(): instanceLimit is not configured or failed to export as environment variable! %s`, ClusterID))
	}
	kv := r.ConsulClient.KV()

	key := fmt.Sprintf(`rdpg/%s/capacity/instances/limit`, ClusterID)
	kvp := &consulapi.KVPair{Key: key, Value: []byte(instanceLimit)}
	_, err = kv.Put(kvp, &consulapi.WriteOptions{})
	if err != nil {
		log.Error(fmt.Sprintf(`rdpg.RDPG<%s>#serviceClusterCapacityStore(): instanceLimit ! %s`, ClusterID, err))
	}

	key = fmt.Sprintf(`rdpg/%s/capacity/instances/allowed`, ClusterID)
	kvp.Key = key
	kvp.Value = []byte(instanceAllowed)
	_, err = kv.Put(kvp, &consulapi.WriteOptions{})
	if err != nil {
		log.Error(fmt.Sprintf(`rdpg.RDPG<%s>#serviceClusterCapacityStore(): instanceAloowed ! %s`, ClusterID, err))
	}

	return
}
開發者ID:predix,項目名稱:rdpg-boshrelease,代碼行數:31,代碼來源:bootstrap.go


注:本文中的github.com/starkandwayne/rdpgd/log.Error函數示例由純淨天空整理自Github/MSDocs等開源代碼及文檔管理平台,相關代碼片段篩選自各路編程大神貢獻的開源項目,源碼版權歸原作者所有,傳播和使用請參考對應項目的License;未經允許,請勿轉載。