更多好文关注 v。golang技术实验室

1、GOGC

GOGC 用于控制GC的处发频率, 其值默认为100,

意为直到自上次垃圾回收后heap size已经增长了100%时GC才触发运行。即是GOGC=100意味着live heap size 每增长一倍,GC触发运行一次。

如设定GOGC=200, 则live heap size 自上次垃圾回收后,增长2倍时,GC触发运行, 总之,其值越大则GC触发运行频率越低, 反之则越高,

如果GOGC=off 则关闭GC.

/*** @Author: zHangSan* @Description:* @File:  main* @Version: 1.0.0* @Date: 2021/4/16 下午4:44*/package mainimport "runtime"func main(){gc()runtime.GC()gc()gc()gc()}func gc(){for i := 0; i< 10000;i++{g := make(map[string]string)g = g}
}
GOGC=100 GODEBUG=gctrace=1 go run ./main.go
gc 1 @0.017s 0%: 0.008+0.48+0.004 ms clock, 0.032+0.33/0.22/0.33+0.019 ms cpu, 4->4->0 MB, 5 MB goal, 4 P
gc 2 @0.031s 0%: 0.003+0.33+0.002 ms clock, 0.014+0.27/0.17/0.57+0.010 ms cpu, 4->4->0 MB, 5 MB goal, 4 P
gc 3 @0.057s 0%: 0.012+0.35+0.003 ms clock, 0.050+0/0.27/0.57+0.012 ms cpu, 4->4->0 MB, 5 MB goal, 4 P
# command-line-arguments
gc 1 @0.002s 9%: 0.023+3.1+0.036 ms clock, 0.093+0.20/2.0/4.1+0.14 ms cpu, 4->7->6 MB, 5 MB goal, 4 P
gc 2 @0.015s 8%: 0.004+4.0+0.003 ms clock, 0.017+1.4/2.8/2.0+0.013 ms cpu, 10->13->13 MB, 12 MB goal, 4 P
gc 1 @0.000s 3%: 0.008+0.13+0.002 ms clock, 0.032+0/0.045/0.16+0.008 ms cpu, 0->0->0 MB, 4 MB goal, 4 P (forced)

可以看到第二次的GC的时候是上次的两倍

2、GOTRACEBACK 打印异常信息

GOTRACEBACK用于控制当异常发生时,系统提供信息的详细程度, 在go 1.5, GOTRACEBACK有4个值。

GOTRACEBACK=0 只输出panic异常信息。
GOTRACEBACK=1 此为go的默认设置值, 输出所有goroutine的stack traces, 除去与go runtime相关的stack frames.
GOTRACEBACK=2 在GOTRACEBACK=1的基础上, 还输出与go runtime相关的stack frames,从而了解哪些goroutines是由go runtime启动运行的。
GOTRACEBACK=crash, 在GOTRACEBACK=2的基础上,go runtime处发进程segfault错误,从而生成core dump, 当然要操作系统允许的情况下, 而不是调用os.Exit。

package mainimport "runtime"func main(){//goGC()gOTraceBack()}
/*****************************GOTRACEBACK-异常发生打印详细信息****************************************/
func gOTraceBack(){panic("kerboom")}
GOTRACEBACK=2 go run main.go
-> % GOTRACEBACK=2 go run main.go
panic: kerboomgoroutine 1 [running]:
panic(0x105ff60, 0x10839b0)/usr/local/go/src/runtime/panic.go:1064 +0x46d fp=0xc000030768 sp=0xc0000306b0 pc=0x1028a2d
main.gOTraceBack(...)/Users/zhangsan/Documents/GitHub/testCode/runArgs/main.go:21
main.main()/Users/zhangsan/Documents/GitHub/testCode/runArgs/main.go:16 +0x39 fp=0xc000030788 sp=0xc000030768 pc=0x1056e89
runtime.main()/usr/local/go/src/runtime/proc.go:203 +0x212 fp=0xc0000307e0 sp=0xc000030788 pc=0x102b452
runtime.goexit()/usr/local/go/src/runtime/asm_amd64.s:1373 +0x1 fp=0xc0000307e8 sp=0xc0000307e0 pc=0x10529d1goroutine 2 [force gc (idle)]:
runtime.gopark(0x1077928, 0x10cd3a0, 0x1411, 0x1)/usr/local/go/src/runtime/proc.go:304 +0xe0 fp=0xc000030fb0 sp=0xc000030f90 pc=0x102b820
runtime.goparkunlock(...)/usr/local/go/src/runtime/proc.go:310
runtime.forcegchelper()/usr/local/go/src/runtime/proc.go:253 +0xb7 fp=0xc000030fe0 sp=0xc000030fb0 pc=0x102b6d7
runtime.goexit()/usr/local/go/src/runtime/asm_amd64.s:1373 +0x1 fp=0xc000030fe8 sp=0xc000030fe0 pc=0x10529d1
created by runtime.init.6/usr/local/go/src/runtime/proc.go:242 +0x35goroutine 3 [GC sweep wait]:
runtime.gopark(0x1077928, 0x10cd460, 0x140c, 0x1)/usr/local/go/src/runtime/proc.go:304 +0xe0 fp=0xc0000317a8 sp=0xc000031788 pc=0x102b820
runtime.goparkunlock(...)/usr/local/go/src/runtime/proc.go:310
runtime.bgsweep(0xc00001c070)/usr/local/go/src/runtime/mgcsweep.go:70 +0x9c fp=0xc0000317d8 sp=0xc0000317a8 pc=0x101aa7c
runtime.goexit()/usr/local/go/src/runtime/asm_amd64.s:1373 +0x1 fp=0xc0000317e0 sp=0xc0000317d8 pc=0x10529d1
created by runtime.gcenable/usr/local/go/src/runtime/mgc.go:214 +0x5cgoroutine 4 [GC scavenge wait]:
runtime.gopark(0x1077928, 0x10cd420, 0x140d, 0x1)/usr/local/go/src/runtime/proc.go:304 +0xe0 fp=0xc000031f78 sp=0xc000031f58 pc=0x102b820
runtime.goparkunlock(...)/usr/local/go/src/runtime/proc.go:310
runtime.bgscavenge(0xc00001c070)/usr/local/go/src/runtime/mgcscavenge.go:237 +0xd0 fp=0xc000031fd8 sp=0xc000031f78 pc=0x1018fd0
runtime.goexit()/usr/local/go/src/runtime/asm_amd64.s:1373 +0x1 fp=0xc000031fe0 sp=0xc000031fd8 pc=0x10529d1
created by runtime.gcenable/usr/local/go/src/runtime/mgc.go:215 +0x7e
exit status 2

GOTRACEBACK 在go 1.6中的变化

GOTRACEBACK=none 只输出panic异常信息。
GOTRACEBACK=single 只输出被认为引发panic异常的那个goroutine的相关信息。
GOTRACEBACK=all 输出所有goroutines的相关信息,除去与go runtime相关的stack frames.
GOTRACEBACK=system 输出所有goroutines的相关信息,包括与go runtime相关的stack frames,从而得知哪些goroutine是go runtime启动运行的。
GOTRACEBACK=crash 与go 1.5相同, 未变化。

为了与go 1.5兼容,0 对应 none, 1 对应 all, 以及 2 对应 system.

注意: 在go 1.6中, 默认,只输出引发panci异常的goroutine的stack trace.

3、控制CPU数量GOMAXPROCS

GOMAXPROCS

GOMAXPROCS 大家比较熟悉, 用于控制操作系统的线程数量, 这些线程用于运行go程序中的goroutines.
到go 1.5的时候, GOMAXPROCS的默认值就是我们的go程序启动时可见的操作系统认为的CPU个数。

注意: 在我们的go程序中使用的操作系统线程数量,也包括:正服务于cgo calls的线程, 阻塞于操作系统calls的线程,
所以go 程序中使用的操作系统线程数量可能大于GOMAXPROCS的值。

4、GODEBUG

GODEBUG=gctrace=1,schedtrace=1000 godoc -http=:8080

1、gctrace

gctrace用途主要是用于跟踪GC的不同阶段的耗时与GC前后的内存量对比。

package mainimport "runtime"func main(){//goGC()//gOTraceBack() 查看crash的时候相信信息goDebugGc()}
/*****************************GODEBUG-异常发生打印详细信息****************************************/
func goDebugGc(){gc()
}
func gc(){for i := 0; i< 10000;i++{g := make(map[string]string)g = g}
}
GODEBUG=gctrace=1 go run  main.go
gc 1 @0.109s 0%: 0.023+0.68+0.005 ms clock, 0.094+0.66/0.44/0+0.021 ms cpu, 4->4->0 MB, 5 MB goal, 4 P
gc 2 @0.136s 0%: 0.004+0.37+0.003 ms clock, 0.019+0.29/0.16/0.68+0.012 ms cpu, 4->4->0 MB, 5 MB goal, 4 P
gc 3 @0.283s 0%: 0.020+0.47+0.003 ms clock, 0.081+0/0.31/0.66+0.014 ms cpu, 4->4->0 MB, 5 MB goal, 4 P
# command-line-arguments
gc 1 @0.019s 6%: 0.057+8.1+0.086 ms clock, 0.23+1.5/5.0/10+0.34 ms cpu, 4->4->3 MB, 5 MB goal, 4 P
gc 4 @0.407s 0%: 0.010+1.0+0.059 ms clock, 0.043+0.34/0.18/0.60+0.23 ms cpu, 4->4->0 MB, 5 MB goal, 4 P
# command-line-arguments
gc 1 @0.002s 12%: 0.007+3.8+0.038 ms clock, 0.029+0.17/2.8/1.8+0.15 ms cpu, 4->6->6 MB, 5 MB goal, 4 P
gc 2 @0.021s 9%: 0.005+8.8+0.003 ms clock, 0.020+0/8.0/1.5+0.014 ms cpu, 9->13->13 MB, 12 MB goal, 4 P
  1. gc 1 : 代表第一次gc

  2. @0.109 : 这是gc的markTermination阶段完成,距离runtime到现在 STW的最后工作,关闭内存屏障,停止后台标记及辅助标记,做一些清理工作

  3. 0% : 当前为止,gc的标记工作(包括两次mark阶段和STW和并发标记)多占用的CPU时间占PU的百分比

  4. 0.023+0.68+0.005 ms clock : 三部分 0。023表示整个过程在mar阶段STW停顿时间(单个P的);
    0.68表示并发标记时间(所有P的);0.005表示markTermination的STW时间(单个P)的

  5. 0.094+0.66/0.44/0+0.021 ms cpu : 0.094三部分,0.094表示整个进程在mark阶段STW停顿时间(0.023 * 8);
    0.66/0.44/0 三块信息,0.66是mutator assists占用的时间,0。44是dedicated mark worker+ fractional mark worker占用的时间,0是idle mark workers占用的时间,这些时间接近
    0.68 * P的个数,+0。021ms 表示整个进程在markTermination阶段Ste停顿时间0。005 * P的个数

  6. 4->4->0 MB 4表示开始mark阶段前的heap_live大小;4表示markTermination阶段之前的heap_live大小,0表示被标记对象的大小

  7. 5MB goal: 表示下一次触发GC的内存占用阀值是5MB,向上取整

  8. 4P :本次gc共有多少P

  • heap_live要结合go的内存管理来理解。因为go按照不同的对象大小,会分配不同页数的span。span是对内存页进行管理的基本单元,每页8k大小。所以肯定会出现span中有内存是空闲着没被用上的。

不过怎么用go先不管,反正是把它划分给程序用了。而heap_live就表示所有span的大小。

而程序到底用了多少呢?就是在GC扫描对象时,扫描到的存活对象大小就是已用的大小。对应上面就是8MB。

  • mark worker分为三种,dedicated、fractional和idle。分别表示标记工作干活时的专注程度。dedicated最专注,除非被抢占打断,否则一直干活。idle最偷懒,干一点活就退出,控制权让给出别的goroutine。它们都是并发标记工作里的worker。

2、schedtrace 调度跟踪

GODEBUG=schedtrace=1000  go run  main.go
SCHED 0ms: gomaxprocs=4 idleprocs=2 threads=4 spinningthreads=1 idlethreads=0 runqueue=0 [0 0 0 0]
# command-line-arguments
SCHED 0ms: gomaxprocs=4 idleprocs=1 threads=4 spinningthreads=1 idlethreads=0 runqueue=0 [1 0 0 0]
# command-line-arguments
SCHED 0ms: gomaxprocs=4 idleprocs=1 threads=5 spinningthreads=1 idlethreads=0 runqueue=0 [0 0 0 0]
SCHED 0ms: gomaxprocs=4 idleprocs=1 threads=4 spinningthreads=1 idlethreads=0 runqueue=0 [1 0 0 0]

可以使运行时在每 X 毫秒发出一次详细的多行信息,信息内容主要包括调度程序、处理器、OS 线程 和 Goroutine 的状态。

sched:每一行都代表调度器的调试信息,后面提示的毫秒数表示启动到现在的运行时间,输出的时间间隔受 schedtrace 的值影响。

gomaxprocs:当前的 CPU 核心数(GOMAXPROCS 的当前值)。

idleprocs:空闲的处理器数量,后面的数字表示当前的空闲数量。

threads:OS 线程数量,后面的数字表示当前正在运行的线程数量。

spinningthreads:自旋状态的 OS 线程数量。

idlethreads:空闲的线程数量。

runqueue:全局队列中中的 Goroutine 数量,而后面的 [0 0 1 1] 则分别代表这 4 个 P 的本地队列正在运行的 Goroutine 数量。

详细信息

GODEBUG=scheddetail=1,schedtrace=1000  go run  main.goSCHED 0ms: gomaxprocs=4 idleprocs=2 threads=4 spinningthreads=1 idlethreads=0 runqueue=0 gcwaiting=0 nmidlelocked=0 stopwait=0 sysmonwait=0P0: status=1 schedtick=0 syscalltick=0 m=0 runqsize=0 gfreecnt=0 timerslen=0P1: status=1 schedtick=0 syscalltick=0 m=3 runqsize=0 gfreecnt=0 timerslen=0P2: status=0 schedtick=0 syscalltick=0 m=-1 runqsize=0 gfreecnt=0 timerslen=0P3: status=0 schedtick=0 syscalltick=0 m=-1 runqsize=0 gfreecnt=0 timerslen=0M3: p=1 curg=-1 mallocing=0 throwing=0 preemptoff= locks=1 dying=0 spinning=false blocked=false lockedg=-1M2: p=-1 curg=-1 mallocing=0 throwing=0 preemptoff= locks=1 dying=0 spinning=false blocked=false lockedg=-1M1: p=-1 curg=17 mallocing=0 throwing=0 preemptoff= locks=0 dying=0 spinning=false blocked=false lockedg=17M0: p=0 curg=-1 mallocing=0 throwing=0 preemptoff= locks=1 dying=0 spinning=false blocked=false lockedg=1G1: status=1() m=-1 lockedm=0G17: status=6() m=1 lockedm=1G2: status=1() m=-1 lockedm=-1
# command-line-arguments
SCHED 0ms: gomaxprocs=4 idleprocs=1 threads=4 spinningthreads=1 idlethreads=0 runqueue=0 [1 0 0 0]
# command-line-arguments
SCHED 0ms: gomaxprocs=4 idleprocs=1 threads=5 spinningthreads=1 idlethreads=0 runqueue=0 gcwaiting=0 nmidlelocked=1 stopwait=0 sysmonwait=0P0: status=1 schedtick=0 syscalltick=0 m=3 runqsize=0 gfreecnt=0 timerslen=0P1: status=1 schedtick=1 syscalltick=0 m=2 runqsize=0 gfreecnt=0 timerslen=0P2: status=1 schedtick=0 syscalltick=0 m=4 runqsize=0 gfreecnt=0 timerslen=0P3: status=0 schedtick=0 syscalltick=0 m=-1 runqsize=0 gfreecnt=0 timerslen=0M4: p=2 curg=-1 mallocing=0 throwing=0 preemptoff= locks=1 dying=0 spinning=false blocked=false lockedg=-1M3: p=0 curg=-1 mallocing=0 throwing=0 preemptoff= locks=1 dying=0 spinning=false blocked=false lockedg=-1M2: p=1 curg=-1 mallocing=0 throwing=0 preemptoff= locks=1 dying=0 spinning=true blocked=false lockedg=-1M1: p=-1 curg=-1 mallocing=0 throwing=0 preemptoff= locks=1 dying=0 spinning=false blocked=false lockedg=-1M0: p=-1 curg=-1 mallocing=0 throwing=0 preemptoff= locks=0 dying=0 spinning=false blocked=true lockedg=1G1: status=1(chan receive) m=-1 lockedm=0G2: status=4(force gc (idle)) m=-1 lockedm=-1G3: status=1() m=-1 lockedm=-1G4: status=4(GC scavenge wait) m=-1 lockedm=-1
SCHED 0ms: gomaxprocs=4 idleprocs=1 threads=5 spinningthreads=1 idlethreads=0 runqueue=0 gcwaiting=0 nmidlelocked=1 stopwait=0 sysmonwait=0P0: status=1 schedtick=0 syscalltick=0 m=3 runqsize=0 gfreecnt=0 timerslen=0P1: status=1 schedtick=2 syscalltick=0 m=2 runqsize=0 gfreecnt=0 timerslen=0P2: status=1 schedtick=0 syscalltick=0 m=4 runqsize=0 gfreecnt=0 timerslen=0P3: status=0 schedtick=0 syscalltick=0 m=-1 runqsize=0 gfreecnt=0 timerslen=0M4: p=2 curg=-1 mallocing=0 throwing=0 preemptoff= locks=1 dying=0 spinning=true blocked=false lockedg=-1M3: p=0 curg=-1 mallocing=0 throwing=0 preemptoff= locks=1 dying=0 spinning=true blocked=false lockedg=-1M2: p=1 curg=-1 mallocing=0 throwing=0 preemptoff= locks=1 dying=0 spinning=false blocked=false lockedg=-1M1: p=-1 curg=-1 mallocing=0 throwing=0 preemptoff= locks=1 dying=0 spinning=false blocked=false lockedg=-1M0: p=-1 curg=-1 mallocing=0 throwing=0 preemptoff= locks=0 dying=0 spinning=false blocked=true lockedg=1G1: status=1(chan receive) m=-1 lockedm=0G2: status=4(force gc (idle)) m=-1 lockedm=-1G3: status=4(GC sweep wait) m=-1 lockedm=-1G4: status=4(GC scavenge wait) m=-1 lockedm=-1

status:G 的运行状态。

m:隶属哪一个 M。

lockedm:是否有锁定 M。

在第一点中我们有提到 G 的运行状态,这对于分析内部流转非常的有用,共涉及如下 9 种状态:

状态 值 含义
_Gidle 0 刚刚被分配,还没有进行初始化。
_Grunnable 1 已经在运行队列中,还没有执行用户代码。
_Grunning 2 不在运行队列里中,已经可以执行用户代码,此时已经分配了 M 和 P。
_Gsyscall 3 正在执行系统调用,此时分配了 M。
_Gwaiting 4 在运行时被阻止,没有执行用户代码,也不在运行队列中,此时它正在某处阻塞等待中。
_Gmoribund_unused 5 尚未使用,但是在 gdb 中进行了硬编码。
_Gdead 6 尚未使用,这个状态可能是刚退出或是刚被初始化,此时它并没有执行用户代码,有可能有也有可能没有分配堆栈。
_Genqueue_unused 7 尚未使用。
_Gcopystack 8 正在复制堆栈,并没有执行用户代码,也不在运行队列中。
在理解了各类的状态的意思后,我们结合上述案例看看,如下:

G1: status=4(semacquire) m=-1 lockedm=-1
G2: status=4(force gc (idle)) m=-1 lockedm=-1
G3: status=4(GC sweep wait) m=-1 lockedm=-1
G17: status=1() m=-1 lockedm=-1
G18: status=2() m=4 lockedm=-1
在这个片段中,G1 的运行状态为 _Gwaiting,并没有分配 M 和锁定。这时候你可能好奇在片段中括号里的是什么东西呢,其实是因为该 status=4 是表示 Goroutine 在运行时时被阻止,而阻止它的事件就是 semacquire 事件,是因为 semacquire 会检查信号量的情况,在合适的时机就调用 goparkunlock 函数,把当前 Goroutine 放进等待队列,并把它设为 _Gwaiting 状态。

那么在实际运行中还有什么原因会导致这种现象呢,我们一起看看,如下:

    waitReasonZero                                    // ""waitReasonGCAssistMarking                         // "GC assist marking"waitReasonIOWait                                  // "IO wait"waitReasonChanReceiveNilChan                      // "chan receive (nil chan)"waitReasonChanSendNilChan                         // "chan send (nil chan)"waitReasonDumpingHeap                             // "dumping heap"waitReasonGarbageCollection                       // "garbage collection"waitReasonGarbageCollectionScan                   // "garbage collection scan"waitReasonPanicWait                               // "panicwait"waitReasonSelect                                  // "select"waitReasonSelectNoCases                           // "select (no cases)"waitReasonGCAssistWait                            // "GC assist wait"waitReasonGCSweepWait                             // "GC sweep wait"waitReasonChanReceive                             // "chan receive"waitReasonChanSend                                // "chan send"waitReasonFinalizerWait                           // "finalizer wait"waitReasonForceGGIdle                             // "force gc (idle)"waitReasonSemacquire                              // "semacquire"waitReasonSleep                                   // "sleep"waitReasonSyncCondWait                            // "sync.Cond.Wait"waitReasonTimerGoroutineIdle                      // "timer goroutine (idle)"waitReasonTraceReaderBlocked                      // "trace reader (blocked)"waitReasonWaitForGCCycle                          // "wait for GC cycle"waitReasonGCWorkerIdle                            // "GC worker (idle)"

我们通过以上 waitReason 可以了解到 Goroutine 会被暂停运行的原因要素,也就是会出现在括号中的事件。

M
p:隶属哪一个 P。

curg:当前正在使用哪个 G。

runqsize:运行队列中的 G 数量。

gfreecnt:可用的G(状态为 Gdead)。

mallocing:是否正在分配内存。

throwing:是否抛出异常。

preemptoff:不等于空字符串的话,保持 curg 在这个 m 上运行。

P
status:P 的运行状态。

schedtick:P 的调度次数。

syscalltick:P 的系统调用次数。

m:隶属哪一个 M。

runqsize:运行队列中的 G 数量。

gfreecnt:可用的G(状态为 Gdead)。

状态 值 含义
_Pidle 0 刚刚被分配,还没有进行进行初始化。
_Prunning 1 当 M 与 P 绑定调用 acquirep 时,P 的状态会改变为 _Prunning。
_Psyscall 2 正在执行系统调用。
_Pgcstop 3 暂停运行,此时系统正在进行 GC,直至 GC 结束后才会转变到下一个状态阶段。
_Pdead 4 废弃,不再使用。

更多好文关注 v。golang技术实验室

golang-如何用全局参数打印程序运行信息相关推荐

  1. Jmeter实现生成全局参数-随机数

    我在做项目的过程中,用的比较多的是[前置处理中]-用户参数 步骤一:添加参数处理器 步骤二:填写项目中可能会用到的一些参数(固定的或者随机的都可以) teacher_name ${__RandomSt ...

  2. 在Java程序中打印java运行时参数

    在Java程序中打印java运行时参数 本文是基于CentOS 7.3系统环境,进行java的学习和使用 CentOS 7.3 1. java运行时参数 Java程序在运行时,主要分为两大类参数,一类 ...

  3. 静态对象、全局对象与程序的运行机制

    静态对象.全局对象与程序的运行机制 1.   在介绍静态对象.全局对象与程序的运行机制之间的关系之前,我们首先看一下atexit函数. atexit函数的声明为:int atexit( void ( ...

  4. 操作无法完成后台打印程序无法运行

    同事反映原共享的打印机无法打印.我删除重新添加时系统提示 操作无法完成后台打印程序无法运行.于是我打开服务找到print spooler服务进程设置自动开启后重新添加问题依旧.在网上查到的方法是 病毒 ...

  5. debug —— set args调试命令(作为程序运行时的参数)

    debug调试 -- set  args 作为程序运行时候的参数 set args作为程序运行时参数: 源代码: 1 #include <stdio.h>2 int main(int ar ...

  6. golang获取程序运行路径

    golang获取程序运行路径: /* 获取程序运行路径 */ func getCurrentDirectory() string { dir, err := filepath.Abs(filepath ...

  7. 程序4-1 对每个命令行参数打印文件类型

    1 //http://blog.chinaunix.net/uid-24549279-id-71355.html 2 /* 3 ==================================== ...

  8. BT源代码学习心得(二):程序运行参数的获取 -- 转贴自 wolfenstein (NeverSayNever)

    BT源代码学习心得(二):程序运行参数的获取 发信人: wolfenstein (NeverSayNever), 个人文集 标  题: BT源代码学习心得(二):程序运行参数的获取 发信站: 水木社区 ...

  9. 15、wxapp - 小程序登录以及全局参数 - 微擎小程序模块应用开发

    通过对 app.js 文件的调整建立,我们接下来要将对应的 微信小程序登录方法,以及全局参数的获取方法对应编写出来. 接口的文件位于PC后端管理目录下 /addons/sx_haodian/wxapp ...

最新文章

  1. android l是哪个版本,从Android L及更高版本开始,setMobileDataEnabled方法不再可调用...
  2. 为什么你应该开始习惯使用 pathlib
  3. Maven打包自动发布到nexus私服
  4. 2021全球自由行报告:我的中国,真好玩!
  5. 深度学习入门读书笔记:Day-14
  6. 正则表达式限制文本框内容
  7. 用matlab建立晶体模型,一种建立多晶体几何模型的方法与流程
  8. python读书心得体会_终于领会学习python的心得体会
  9. HarmonyOS APP 开发入门
  10. 南阳oj入门题-谁是最好的coder
  11. C语言判断一个数是奇数还是偶数
  12. 苹果电脑网速怎么测试软件,macbookpro怎么检测网速?
  13. STM32CubeIDE+FREERTOS踩坑记录
  14. 安卓证书在线制作工具
  15. edge 错误 客户端和服务器不支持常用的 SSL 协议版本或密码套件
  16. 面经(各种面试内容)
  17. openssl给内网IP生成ca证书(ssl证书)
  18. C语言:一个球从100m高度自由落下,每次落地后反跳回原高度的一半,再落下,再反弹;求它在第10次落地时,共经过多少米,第10次反弹多高;
  19. 哒哒哒哒哒哒,哒哒哒哒哒哒哒哒
  20. python财务报表书籍_清华大学出版社-图书详情-《从零开始学看财报(白金版)》...

热门文章

  1. layui中table表格内容过多自动换行
  2. mysql数据库下载、安装、使用
  3. 使用Python获取国际版淘宝AliExpress的商品信息
  4. 数学符号 - 罗马字母
  5. 服务器启动显示按f1f2f10,电脑开机提示按f1f2f5 电脑开机要按F1F2F5
  6. python读取二进制文件 \xff\xfe \xef\xbb\xbf
  7. Pytorch系列笔记(九)
  8. win10无法连接到win7系统更新服务器,win10系统提示无法连接到windows服务的解决方法...
  9. 虚拟机里centos7怎么联网?费时许久终于搞定!!
  10. 2014 android 新技术,向友商学习 Android 12新功能前瞻:似曾相识