main

func main() {    g := getg()    g.m.g0.racectx = 0    if sys.PtrSize == 8 {        maxstacksize = 1000000000    } else {        maxstacksize = 250000000    }    maxstackceiling = 2 * maxstacksize    // Allow newproc to start new Ms.    mainStarted = true    if GOARCH != "wasm" { // no threads on wasm yet, so no sysmon        // For runtime_syscall_doAllThreadsSyscall, we        // register sysmon is not ready for the world to be        // stopped.        atomic.Store(&sched.sysmonStarting, 1)        systemstack(func() {            newm(sysmon, nil, -1)        })    }    // Lock the main goroutine onto this, the main OS thread,    // during initialization. Most programs won't care, but a few    // do require certain calls to be made by the main thread.    // Those can arrange for main.main to run in the main thread    // by calling runtime.LockOSThread during initialization    // to preserve the lock.    lockOSThread()    if g.m != &m0 {        throw("runtime.main not on m0")    }    m0.doesPark = true    // Record when the world started.    // Must be before doInit for tracing init.    runtimeInitTime = nanotime()    if runtimeInitTime == 0 {        throw("nanotime returning zero")    }    if debug.inittrace != 0 {        inittrace.id = getg().goid        inittrace.active = true    }    doInit(&runtime_inittask) // Must be before defer.    // Defer unlock so that runtime.Goexit during init does the unlock too.    needUnlock := true    defer func() {        if needUnlock {            unlockOSThread()        }    }()    gcenable()    main_init_done = make(chan bool)    if iscgo {        if _cgo_thread_start == nil {            throw("_cgo_thread_start missing")        }        if GOOS != "windows" {            if _cgo_setenv == nil {                throw("_cgo_setenv missing")            }            if _cgo_unsetenv == nil {                throw("_cgo_unsetenv missing")            }        }        if _cgo_notify_runtime_init_done == nil {            throw("_cgo_notify_runtime_init_done missing")        }        // Start the template thread in case we enter Go from        // a C-created thread and need to create a new thread.        startTemplateThread()        cgocall(_cgo_notify_runtime_init_done, nil)    }    doInit(&main_inittask)    // Disable init tracing after main init done to avoid overhead    // of collecting statistics in malloc and newproc    inittrace.active = false    close(main_init_done)    needUnlock = false    unlockOSThread()    if isarchive || islibrary {        // A program compiled with -buildmode=c-archive or c-shared        // has a main, but it is not executed.        return    }    fn := main_main // make an indirect call, as the linker doesn't know the address of the main package when laying down the runtime    fn()    if raceenabled {        racefini()    }    // Make racy client program work: if panicking on    // another goroutine at the same time as main returns,    // let the other goroutine finish printing the panic trace.    // Once it does, it will exit. See issues 3934 and 20018.    if atomic.Load(&runningPanicDefers) != 0 {        // Running deferred functions should not take long.        for c := 0; c < 1000; c++ {            if atomic.Load(&runningPanicDefers) == 0 {                break            }            Gosched()        }    }    if atomic.Load(&panicking) != 0 {        gopark(nil, nil, waitReasonPanicWait, traceEvGoStop, 1)    }    exit(0)    for {        var x *int32        *x = 0    }}
  1. 执行runtime init
  2. 执行main init
  3. 执行main main