文章目录

  • Gorm之gorm.io/gorm源码
    • 1.gorm.Open函数
    • 2.gorm.Dialector接口
    • 3.gorm.Config结构体
    • 4.gorm.DB结构体
      • 4.1gorm.DB结构体
      • 4.2AutoMigrate方法
      • 4.3Migrator方法
      • 4.4Create方法
      • 4.5CreateInBatches方法
      • 4.6Save方法
      • 4.7First方法
      • 4.8Take方法
      • 4.9Last方法
      • 4.10Find方法
      • 4.11FindInBatches方法
      • 4.12assignInterfacesToValue方法
      • 4.13FirstOrInit方法
      • 4.14FirstOrCreate方法
      • 4.15Update方法
      • 4.16Updates方法
      • 4.17UpdateColumn方法
      • 4.18UpdateColumns方法
      • 4.19Delete方法
      • 4.20Count方法
      • 4.21Row()方法
      • 4.22Rows()方法
      • 4.23Scan方法
      • 4.24Pluck方法
      • 4.25ScanRows方法
      • 4.26Connection方法
      • 4.27Transaction方法
      • 4.28Begin方法
      • 4.29Commit方法
      • 4.30Rollback方法
      • 4.31SavePoint方法
      • 4.32RollbackTo方法
      • 4.33Exec方法
    • 5.gorm.Option接口
    • 6.gorm.Migrator接口
    • 7.ColumnType接口

Gorm之gorm.io/gorm源码

注:本文是基于Windos系统上 gorm.io/gorm@v1.23.4进行讲解

1.gorm.Open函数

// Open initialize db session based on dialector
//返回:gorm.DB结构体
func Open(dialector Dialector, opts ...Option) (db *DB, err error) {config := &Config{}sort.Slice(opts, func(i, j int) bool {_, isConfig := opts[i].(*Config)_, isConfig2 := opts[j].(*Config)return isConfig && !isConfig2})for _, opt := range opts {if opt != nil {if applyErr := opt.Apply(config); applyErr != nil {return nil, applyErr}defer func(opt Option) {if errr := opt.AfterInitialize(db); errr != nil {err = errr}}(opt)}}if d, ok := dialector.(interface{ Apply(*Config) error }); ok {if err = d.Apply(config); err != nil {return}}if config.NamingStrategy == nil {config.NamingStrategy = schema.NamingStrategy{}}if config.Logger == nil {config.Logger = logger.Default}if config.NowFunc == nil {config.NowFunc = func() time.Time { return time.Now().Local() }}if dialector != nil {config.Dialector = dialector}if config.Plugins == nil {config.Plugins = map[string]Plugin{}}if config.cacheStore == nil {config.cacheStore = &sync.Map{}}db = &DB{Config: config, clone: 1}db.callbacks = initializeCallbacks(db)if config.ClauseBuilders == nil {config.ClauseBuilders = map[string]clause.ClauseBuilder{}}if config.Dialector != nil {err = config.Dialector.Initialize(db)}preparedStmt := &PreparedStmtDB{ConnPool:    db.ConnPool,Stmts:       map[string]Stmt{},Mux:         &sync.RWMutex{},PreparedSQL: make([]string, 0, 100),}db.cacheStore.Store(preparedStmtDBKey, preparedStmt)if config.PrepareStmt {db.ConnPool = preparedStmt}db.Statement = &Statement{DB:       db,ConnPool: db.ConnPool,Context:  context.Background(),Clauses:  map[string]clause.Clause{},}if err == nil && !config.DisableAutomaticPing {if pinger, ok := db.ConnPool.(interface{ Ping() error }); ok {err = pinger.Ping()}}if err != nil {config.Logger.Error(context.Background(), "failed to initialize database, got error %v", err)}return
}

2.gorm.Dialector接口

// Dialector GORM database dialector
type Dialector interface {Name() stringInitialize(*DB) errorMigrator(db *DB) MigratorDataTypeOf(*schema.Field) stringDefaultValueOf(*schema.Field) clause.ExpressionBindVarTo(writer clause.Writer, stmt *Statement, v interface{})QuoteTo(clause.Writer, string)Explain(sql string, vars ...interface{}) string
}

3.gorm.Config结构体

// Config GORM config
type Config struct {// GORM perform single create, update, delete operations in transactions by default to ensure database data integrity// You can disable it by setting `SkipDefaultTransaction` to trueSkipDefaultTransaction bool// NamingStrategy tables, columns naming strategyNamingStrategy schema.Namer// FullSaveAssociations full save associationsFullSaveAssociations bool// LoggerLogger logger.Interface// NowFunc the function to be used when creating a new timestampNowFunc func() time.Time// DryRun generate sql without executeDryRun bool// PrepareStmt executes the given query in cached statementPrepareStmt bool// DisableAutomaticPingDisableAutomaticPing bool// DisableForeignKeyConstraintWhenMigratingDisableForeignKeyConstraintWhenMigrating bool// DisableNestedTransaction disable nested transactionDisableNestedTransaction bool// AllowGlobalUpdate allow global updateAllowGlobalUpdate bool// QueryFields executes the SQL query with all fields of the tableQueryFields bool// CreateBatchSize default create batch sizeCreateBatchSize int// ClauseBuilders clause builderClauseBuilders map[string]clause.ClauseBuilder// ConnPool db conn poolConnPool ConnPool// Dialector database dialectorDialector// Plugins registered pluginsPlugins map[string]Plugincallbacks  *callbackscacheStore *sync.Map
}

4.gorm.DB结构体

4.1gorm.DB结构体

// DB GORM DB definition
type DB struct {*Config      //gorm.Config结构体Error        errorRowsAffected int64Statement    *Statementclone        int
}

4.2AutoMigrate方法

// AutoMigrate run auto migration for given models
func (db *DB) AutoMigrate(dst ...interface{}) error {return db.Migrator().AutoMigrate(dst...)
}

4.3Migrator方法

// Migrator returns migrator
func (db *DB) Migrator() Migrator {tx := db.getInstance()// apply scopes to migratorfor len(tx.Statement.scopes) > 0 {scopes := tx.Statement.scopestx.Statement.scopes = nilfor _, scope := range scopes {tx = scope(tx)}}return tx.Dialector.Migrator(tx.Session(&Session{}))
}

4.4Create方法

// Create insert the value into database
func (db *DB) Create(value interface{}) (tx *DB) {if db.CreateBatchSize > 0 {return db.CreateInBatches(value, db.CreateBatchSize)}tx = db.getInstance()tx.Statement.Dest = valuereturn tx.callbacks.Create().Execute(tx)
}

4.5CreateInBatches方法

// CreateInBatches insert the value in batches into database
func (db *DB) CreateInBatches(value interface{}, batchSize int) (tx *DB) {reflectValue := reflect.Indirect(reflect.ValueOf(value))switch reflectValue.Kind() {case reflect.Slice, reflect.Array:var rowsAffected int64tx = db.getInstance()callFc := func(tx *DB) error {// the reflection length judgment of the optimized valuereflectLen := reflectValue.Len()for i := 0; i < reflectLen; i += batchSize {ends := i + batchSizeif ends > reflectLen {ends = reflectLen}subtx := tx.getInstance()subtx.Statement.Dest = reflectValue.Slice(i, ends).Interface()subtx.callbacks.Create().Execute(subtx)if subtx.Error != nil {return subtx.Error}rowsAffected += subtx.RowsAffected}return nil}if tx.SkipDefaultTransaction {tx.AddError(callFc(tx.Session(&Session{})))} else {tx.AddError(tx.Transaction(callFc))}tx.RowsAffected = rowsAffecteddefault:tx = db.getInstance()tx.Statement.Dest = valuetx = tx.callbacks.Create().Execute(tx)}return
}

4.6Save方法

// Save update value in database, if the value doesn't have primary key, will insert it
func (db *DB) Save(value interface{}) (tx *DB) {tx = db.getInstance()tx.Statement.Dest = valuereflectValue := reflect.Indirect(reflect.ValueOf(value))switch reflectValue.Kind() {case reflect.Slice, reflect.Array:if _, ok := tx.Statement.Clauses["ON CONFLICT"]; !ok {tx = tx.Clauses(clause.OnConflict{UpdateAll: true})}tx = tx.callbacks.Create().Execute(tx.Set("gorm:update_track_time", true))case reflect.Struct:if err := tx.Statement.Parse(value); err == nil && tx.Statement.Schema != nil {for _, pf := range tx.Statement.Schema.PrimaryFields {if _, isZero := pf.ValueOf(tx.Statement.Context, reflectValue); isZero {return tx.callbacks.Create().Execute(tx)}}}fallthroughdefault:selectedUpdate := len(tx.Statement.Selects) != 0// when updating, use all fields including those zero-value fieldsif !selectedUpdate {tx.Statement.Selects = append(tx.Statement.Selects, "*")}tx = tx.callbacks.Update().Execute(tx)if tx.Error == nil && tx.RowsAffected == 0 && !tx.DryRun && !selectedUpdate {result := reflect.New(tx.Statement.Schema.ModelType).Interface()if err := tx.Session(&Session{}).Take(result).Error; errors.Is(err, ErrRecordNotFound) {return tx.Create(value)}}}return
}

4.7First方法

// First find first record that match given conditions, order by primary key
func (db *DB) First(dest interface{}, conds ...interface{}) (tx *DB) {tx = db.Limit(1).Order(clause.OrderByColumn{Column: clause.Column{Table: clause.CurrentTable, Name: clause.PrimaryKey},})if len(conds) > 0 {if exprs := tx.Statement.BuildCondition(conds[0], conds[1:]...); len(exprs) > 0 {tx.Statement.AddClause(clause.Where{Exprs: exprs})}}tx.Statement.RaiseErrorOnNotFound = truetx.Statement.Dest = destreturn tx.callbacks.Query().Execute(tx)
}

4.8Take方法

// Take return a record that match given conditions, the order will depend on the database implementation
func (db *DB) Take(dest interface{}, conds ...interface{}) (tx *DB) {tx = db.Limit(1)if len(conds) > 0 {if exprs := tx.Statement.BuildCondition(conds[0], conds[1:]...); len(exprs) > 0 {tx.Statement.AddClause(clause.Where{Exprs: exprs})}}tx.Statement.RaiseErrorOnNotFound = truetx.Statement.Dest = destreturn tx.callbacks.Query().Execute(tx)
}

4.9Last方法

// Last find last record that match given conditions, order by primary key
func (db *DB) Last(dest interface{}, conds ...interface{}) (tx *DB) {tx = db.Limit(1).Order(clause.OrderByColumn{Column: clause.Column{Table: clause.CurrentTable, Name: clause.PrimaryKey},Desc:   true,})if len(conds) > 0 {if exprs := tx.Statement.BuildCondition(conds[0], conds[1:]...); len(exprs) > 0 {tx.Statement.AddClause(clause.Where{Exprs: exprs})}}tx.Statement.RaiseErrorOnNotFound = truetx.Statement.Dest = destreturn tx.callbacks.Query().Execute(tx)
}

4.10Find方法

// Find find records that match given conditions
func (db *DB) Find(dest interface{}, conds ...interface{}) (tx *DB) {tx = db.getInstance()if len(conds) > 0 {if exprs := tx.Statement.BuildCondition(conds[0], conds[1:]...); len(exprs) > 0 {tx.Statement.AddClause(clause.Where{Exprs: exprs})}}tx.Statement.Dest = destreturn tx.callbacks.Query().Execute(tx)
}

4.11FindInBatches方法

// FindInBatches find records in batches
func (db *DB) FindInBatches(dest interface{}, batchSize int, fc func(tx *DB, batch int) error) *DB {var (tx = db.Order(clause.OrderByColumn{Column: clause.Column{Table: clause.CurrentTable, Name: clause.PrimaryKey},}).Session(&Session{})queryDB      = txrowsAffected int64batch        int)for {result := queryDB.Limit(batchSize).Find(dest)rowsAffected += result.RowsAffectedbatch++if result.Error == nil && result.RowsAffected != 0 {tx.AddError(fc(result, batch))} else if result.Error != nil {tx.AddError(result.Error)}if tx.Error != nil || int(result.RowsAffected) < batchSize {break}// Optimize for-breakresultsValue := reflect.Indirect(reflect.ValueOf(dest))if result.Statement.Schema.PrioritizedPrimaryField == nil {tx.AddError(ErrPrimaryKeyRequired)break}primaryValue, _ := result.Statement.Schema.PrioritizedPrimaryField.ValueOf(tx.Statement.Context, resultsValue.Index(resultsValue.Len()-1))queryDB = tx.Clauses(clause.Gt{Column: clause.Column{Table: clause.CurrentTable, Name: clause.PrimaryKey}, Value: primaryValue})}tx.RowsAffected = rowsAffectedreturn tx
}

4.12assignInterfacesToValue方法

func (db *DB) assignInterfacesToValue(values ...interface{}) {for _, value := range values {switch v := value.(type) {case []clause.Expression:for _, expr := range v {if eq, ok := expr.(clause.Eq); ok {switch column := eq.Column.(type) {case string:if field := db.Statement.Schema.LookUpField(column); field != nil {db.AddError(field.Set(db.Statement.Context, db.Statement.ReflectValue, eq.Value))}case clause.Column:if field := db.Statement.Schema.LookUpField(column.Name); field != nil {db.AddError(field.Set(db.Statement.Context, db.Statement.ReflectValue, eq.Value))}}} else if andCond, ok := expr.(clause.AndConditions); ok {db.assignInterfacesToValue(andCond.Exprs)}}case clause.Expression, map[string]string, map[interface{}]interface{}, map[string]interface{}:if exprs := db.Statement.BuildCondition(value); len(exprs) > 0 {db.assignInterfacesToValue(exprs)}default:if s, err := schema.Parse(value, db.cacheStore, db.NamingStrategy); err == nil {reflectValue := reflect.Indirect(reflect.ValueOf(value))switch reflectValue.Kind() {case reflect.Struct:for _, f := range s.Fields {if f.Readable {if v, isZero := f.ValueOf(db.Statement.Context, reflectValue); !isZero {if field := db.Statement.Schema.LookUpField(f.Name); field != nil {db.AddError(field.Set(db.Statement.Context, db.Statement.ReflectValue, v))}}}}}} else if len(values) > 0 {if exprs := db.Statement.BuildCondition(values[0], values[1:]...); len(exprs) > 0 {db.assignInterfacesToValue(exprs)}return}}}
}

4.13FirstOrInit方法

// FirstOrInit gets the first matched record or initialize a new instance with given conditions (only works with struct or map conditions)
func (db *DB) FirstOrInit(dest interface{}, conds ...interface{}) (tx *DB) {queryTx := db.Limit(1).Order(clause.OrderByColumn{Column: clause.Column{Table: clause.CurrentTable, Name: clause.PrimaryKey},})if tx = queryTx.Find(dest, conds...); queryTx.RowsAffected == 0 {if c, ok := tx.Statement.Clauses["WHERE"]; ok {if where, ok := c.Expression.(clause.Where); ok {tx.assignInterfacesToValue(where.Exprs)}}// initialize with attrs, condsif len(tx.Statement.attrs) > 0 {tx.assignInterfacesToValue(tx.Statement.attrs...)}}// initialize with attrs, condsif len(tx.Statement.assigns) > 0 {tx.assignInterfacesToValue(tx.Statement.assigns...)}return
}

4.14FirstOrCreate方法

// FirstOrCreate gets the first matched record or create a new one with given conditions (only works with struct, map conditions)
func (db *DB) FirstOrCreate(dest interface{}, conds ...interface{}) (tx *DB) {queryTx := db.Limit(1).Order(clause.OrderByColumn{Column: clause.Column{Table: clause.CurrentTable, Name: clause.PrimaryKey},})if tx = queryTx.Find(dest, conds...); tx.Error == nil {if tx.RowsAffected == 0 {if c, ok := tx.Statement.Clauses["WHERE"]; ok {if where, ok := c.Expression.(clause.Where); ok {tx.assignInterfacesToValue(where.Exprs)}}// initialize with attrs, condsif len(tx.Statement.attrs) > 0 {tx.assignInterfacesToValue(tx.Statement.attrs...)}// initialize with attrs, condsif len(tx.Statement.assigns) > 0 {tx.assignInterfacesToValue(tx.Statement.assigns...)}return tx.Create(dest)} else if len(db.Statement.assigns) > 0 {exprs := tx.Statement.BuildCondition(db.Statement.assigns[0], db.Statement.assigns[1:]...)assigns := map[string]interface{}{}for _, expr := range exprs {if eq, ok := expr.(clause.Eq); ok {switch column := eq.Column.(type) {case string:assigns[column] = eq.Valuecase clause.Column:assigns[column.Name] = eq.Valuedefault:}}}return tx.Model(dest).Updates(assigns)}}return tx
}

4.15Update方法

// Update update attributes with callbacks, refer: https://gorm.io/docs/update.html#Update-Changed-Fields
func (db *DB) Update(column string, value interface{}) (tx *DB) {tx = db.getInstance()tx.Statement.Dest = map[string]interface{}{column: value}return tx.callbacks.Update().Execute(tx)
}

4.16Updates方法


// Updates update attributes with callbacks, refer: https://gorm.io/docs/update.html#Update-Changed-Fields
func (db *DB) Updates(values interface{}) (tx *DB) {tx = db.getInstance()tx.Statement.Dest = valuesreturn tx.callbacks.Update().Execute(tx)
}

4.17UpdateColumn方法


func (db *DB) UpdateColumn(column string, value interface{}) (tx *DB) {tx = db.getInstance()tx.Statement.Dest = map[string]interface{}{column: value}tx.Statement.SkipHooks = truereturn tx.callbacks.Update().Execute(tx)
}

4.18UpdateColumns方法

func (db *DB) UpdateColumns(values interface{}) (tx *DB) {tx = db.getInstance()tx.Statement.Dest = valuestx.Statement.SkipHooks = truereturn tx.callbacks.Update().Execute(tx)
}

4.19Delete方法

// Delete delete value match given conditions, if the value has primary key, then will including the primary key as condition
func (db *DB) Delete(value interface{}, conds ...interface{}) (tx *DB) {tx = db.getInstance()if len(conds) > 0 {if exprs := tx.Statement.BuildCondition(conds[0], conds[1:]...); len(exprs) > 0 {tx.Statement.AddClause(clause.Where{Exprs: exprs})}}tx.Statement.Dest = valuereturn tx.callbacks.Delete().Execute(tx)
}

4.20Count方法

func (db *DB) Count(count *int64) (tx *DB) {

4.21Row()方法

func (db *DB) Row() *sql.Row {tx := db.getInstance().Set("rows", false)tx = tx.callbacks.Row().Execute(tx)row, ok := tx.Statement.Dest.(*sql.Row)if !ok && tx.DryRun {db.Logger.Error(tx.Statement.Context, ErrDryRunModeUnsupported.Error())}return row
}

4.22Rows()方法


func (db *DB) Rows() (*sql.Rows, error) {tx := db.getInstance().Set("rows", true)tx = tx.callbacks.Row().Execute(tx)rows, ok := tx.Statement.Dest.(*sql.Rows)if !ok && tx.DryRun && tx.Error == nil {tx.Error = ErrDryRunModeUnsupported}return rows, tx.Error
}

4.23Scan方法

// Scan scan value to a struct
func (db *DB) Scan(dest interface{}) (tx *DB) {config := *db.ConfigcurrentLogger, newLogger := config.Logger, logger.Recorder.New()config.Logger = newLoggertx = db.getInstance()tx.Config = &configif rows, err := tx.Rows(); err == nil {if rows.Next() {tx.ScanRows(rows, dest)} else {tx.RowsAffected = 0}tx.AddError(rows.Close())}currentLogger.Trace(tx.Statement.Context, newLogger.BeginAt, func() (string, int64) {return newLogger.SQL, tx.RowsAffected}, tx.Error)tx.Logger = currentLoggerreturn
}

4.24Pluck方法

// Pluck used to query single column from a model as a map
//     var ages []int64
//     db.Model(&users).Pluck("age", &ages)
func (db *DB) Pluck(column string, dest interface{}) (tx *DB) {tx = db.getInstance()if tx.Statement.Model != nil {if tx.Statement.Parse(tx.Statement.Model) == nil {if f := tx.Statement.Schema.LookUpField(column); f != nil {column = f.DBName}}}if len(tx.Statement.Selects) != 1 {fields := strings.FieldsFunc(column, utils.IsValidDBNameChar)tx.Statement.AddClauseIfNotExists(clause.Select{Distinct: tx.Statement.Distinct,Columns:  []clause.Column{{Name: column, Raw: len(fields) != 1}},})}tx.Statement.Dest = destreturn tx.callbacks.Query().Execute(tx)
}

4.25ScanRows方法

func (db *DB) ScanRows(rows *sql.Rows, dest interface{}) error {tx := db.getInstance()if err := tx.Statement.Parse(dest); !errors.Is(err, schema.ErrUnsupportedDataType) {tx.AddError(err)}tx.Statement.Dest = desttx.Statement.ReflectValue = reflect.ValueOf(dest)for tx.Statement.ReflectValue.Kind() == reflect.Ptr {elem := tx.Statement.ReflectValue.Elem()if !elem.IsValid() {elem = reflect.New(tx.Statement.ReflectValue.Type().Elem())tx.Statement.ReflectValue.Set(elem)}tx.Statement.ReflectValue = elem}Scan(rows, tx, ScanInitialized)return tx.Error
}

4.26Connection方法

// Connection  use a db conn to execute Multiple commands,this conn will put conn pool after it is executed.
func (db *DB) Connection(fc func(tx *DB) error) (err error) {if db.Error != nil {return db.Error}tx := db.getInstance()sqlDB, err := tx.DB()if err != nil {return}conn, err := sqlDB.Conn(tx.Statement.Context)if err != nil {return}defer conn.Close()tx.Statement.ConnPool = connreturn fc(tx)
}

4.27Transaction方法

// Transaction start a transaction as a block, return error will rollback, otherwise to commit.
func (db *DB) Transaction(fc func(tx *DB) error, opts ...*sql.TxOptions) (err error) {}

4.28Begin方法

// Begin begins a transaction
func (db *DB) Begin(opts ...*sql.TxOptions) *DB {}

4.29Commit方法

// Commit commit a transaction
func (db *DB) Commit() *DB {if committer, ok := db.Statement.ConnPool.(TxCommitter); ok && committer != nil && !reflect.ValueOf(committer).IsNil() {db.AddError(committer.Commit())} else {db.AddError(ErrInvalidTransaction)}return db
}

4.30Rollback方法

// Rollback rollback a transaction
func (db *DB) Rollback() *DB {}

4.31SavePoint方法

func (db *DB) SavePoint(name string) *DB {}

4.32RollbackTo方法

func (db *DB) RollbackTo(name string) *DB {}

4.33Exec方法

// Exec execute raw sql
func (db *DB) Exec(sql string, values ...interface{}) (tx *DB) {}

5.gorm.Option接口

// Option gorm option interface
type Option interface {Apply(*Config) errorAfterInitialize(*DB) error
}

6.gorm.Migrator接口

// Migrator migrator interface
type Migrator interface {// AutoMigrateAutoMigrate(dst ...interface{}) error// DatabaseCurrentDatabase() stringFullDataTypeOf(*schema.Field) clause.Expr// TablesCreateTable(dst ...interface{}) errorDropTable(dst ...interface{}) errorHasTable(dst interface{}) boolRenameTable(oldName, newName interface{}) errorGetTables() (tableList []string, err error)// ColumnsAddColumn(dst interface{}, field string) errorDropColumn(dst interface{}, field string) errorAlterColumn(dst interface{}, field string) errorMigrateColumn(dst interface{}, field *schema.Field, columnType ColumnType) errorHasColumn(dst interface{}, field string) boolRenameColumn(dst interface{}, oldName, field string) errorColumnTypes(dst interface{}) ([]ColumnType, error)// ViewsCreateView(name string, option ViewOption) errorDropView(name string) error// ConstraintsCreateConstraint(dst interface{}, name string) errorDropConstraint(dst interface{}, name string) errorHasConstraint(dst interface{}, name string) bool// IndexesCreateIndex(dst interface{}, name string) errorDropIndex(dst interface{}, name string) errorHasIndex(dst interface{}, name string) boolRenameIndex(dst interface{}, oldName, newName string) error
}

7.ColumnType接口

// ColumnType column type interface
type ColumnType interface {Name() stringDatabaseTypeName() string                 // varcharColumnType() (columnType string, ok bool) // varchar(64)PrimaryKey() (isPrimaryKey bool, ok bool)AutoIncrement() (isAutoIncrement bool, ok bool)Length() (length int64, ok bool)DecimalSize() (precision int64, scale int64, ok bool)Nullable() (nullable bool, ok bool)Unique() (unique bool, ok bool)ScanType() reflect.TypeComment() (value string, ok bool)DefaultValue() (value string, ok bool)
}

Gorm之gorm.io/gorm源码相关推荐

  1. Thrift异步IO服务器源码分析

    http://yanyiwu.com/work/2014/12/06/thrift-tnonblockingserver-analysis.html 最近在使用 libevent 开发项目,想起之前写 ...

  2. Java IO流源码学习之二(Buffered字节流)

    本文记录BufferedInputStream,BufferedOutputStream两个带缓冲的输入输出流. BufferedInputStream继承于FilterInputStream,Buf ...

  3. java源码之 io 流源码解读(三)

    前面两篇已经基本介绍了基本输入流和包装输入流.  因此接下来的路要好走的多. 因为它们都是对称的,输入流的很多的读方法对应的是相应的写方法.还有就是发现自己原来的一个误区,就是flushable并不针 ...

  4. io.h源码 检查文件是否存在

    请问在windows上使用什么API来检查文件是否存在? http://topic.csdn.net/u/20080929/00/48833cf7-125f-4075-881f-614a51fc3e6 ...

  5. java 快速io_Java编程在ICPC快速IO实现源码

    本文将介绍Java在ICPC快速IO实现方法,下面看看具体代码. 不处理EOF: import java.io.OutputStream; import java.io.IOException; im ...

  6. python IO多路复用源码

    # #非阻塞 # from socket import * # from time import sleep,ctime # s=socket() # s.bind(('0.0.0.0',7895)) ...

  7. Thrift之Protocol源码分析

     之前写过两篇关于 Thrift 的相关文章. Thrift源码剖析 Thrift异步IO服务器源码分析 也算是对Thrift比较熟悉,不过对 Thrift 里面的 Protocol 部分还是黑盒 ...

  8. API查q绑定带反查sgk带接口API文件源码

    API查q绑定带反查sgk带接口AP 源码下载地址:apiskey.io接口源码https://xiaobaizhan.lanzouw.com/b01k73bng

  9. 内含扩容源码的面试题,目标是手写HashMap!

    基础知识 说说List.Set.Map三者的区别 List(对付顺序的好帮手):List接口存储一组不唯一(可以用多个元素引用相同的对象),有序的对象. Set(注重第一无二的性质):不允许重复的集合 ...

  10. 收藏的有用博客及源码地址

    学习路线 http://blog.csdn.net/singwhatiwanna/article/details/49560409 基础学习类 使用Handler容易产生的内存泄露以及介绍下Java的 ...

最新文章

  1. 一名合格的运维工程师的历练之路
  2. Linux下Sniffer程序的实现
  3. 蚂蚁金服11.11:支付宝和蚂蚁花呗的技术架构及实践
  4. Innodb隔离级别的实现原理
  5. SSRF(服务端请求伪造)
  6. python3怎样交换数字顺序_python中怎么交换列的顺序
  7. Linux系统编程---11(会话,守护进程,创建守护进程)
  8. BZOJ4321:queue2(DP)
  9. git 上传了一个非常大的文件,删除文件
  10. 在这个学术被国界化的日子,我有点怀念爱因斯坦。
  11. python机器学习应用mooc_(3)决策树
  12. VP9与H.265的6个不同点
  13. 对人工智能的初步认识
  14. 从后端到页面:如何全方位监控 Ruby 应用?
  15. 油猴插件的介绍和安装详解脚本的介绍和添加举例
  16. 招行首发芭比娃娃MP3
  17. android日期分组相册,按时间分类的自定义相册
  18. 女神节送什么给礼物女友好,2022女神节送礼合集
  19. VisualVM的配置和使用
  20. Java对接阿里云短信平台(快速上手)

热门文章

  1. vue项目中引入插件
  2. linux 查看redis日志文件,Ubuntu上Redis日志文件的位置
  3. 华硕h410csm怎么开启_华硕主板怎么设置U盘启动 华硕主板设置U盘启动教程
  4. 写手们要下岗了?百度开启AI智能写作平台
  5. Linux Crontab 定时任务
  6. opencv学习笔记五十三:训练自己的级联分类器
  7. QNX演示自动在CES 2016驱动模块-QNX自动驾驶
  8. 关于Android SDK下载和更新失败的解决方法
  9. 含稀土铕双功能荧光磁性纳米粒子/包裹磁性稀土荧光复合物纳米微球的性能与表征
  10. 产品经理入门到大神的资料全推荐