OpenIM JSSDK (三)
从下面的函数开始:
func (wsRouter *WsFuncRouter) GetSelfUserInfo(input string, operationID string) {
userWorker := open_im_sdk.GetUserWorker(wsRouter.uId)
if !wsRouter.checkResourceLoadingAndKeysIn(userWorker, input, operationID, runFuncName(), nil) {
return
}
userWorker.User().GetSelfUserInfo(&BaseSuccessFailed{runFuncName(), operationID, wsRouter.uId}, operationID)
}
这段代码定义了 WsFuncRouter
结构的一个方法 SetSelfInfo
。该方法主要用于设置用户信息。我们来逐步分析它的功能和逻辑:
获取与指定用户ID相关的登录管理器:
userWorker := open_im_sdk.GetUserWorker(wsRouter.uId)
这一行代码调用了之前解释过的
GetUserWorker
函数,传入的参数是wsRouter
结构体中存储的uId
(用户ID)。该函数会返回与指定用户ID相关的LoginMgr
实例(或者为此用户ID创建一个新的实例)。检查资源是否已加载并检查关键信息:
if !wsRouter.checkResourceLoadingAndKeysIn(userWorker, userInfo, operationID, runFuncName(), nil) { return }
这里调用了
checkResourceLoadingAndKeysIn
方法(该方法的具体实现未提供)。这个方法似乎进行一些前置检查,例如资源是否已经加载、是否存在必要的关键信息等。如果这些检查不通过(方法返回false
),那么SetSelfInfo
方法会提前返回并不执行后续的逻辑。设置用户信息:
userWorker.User().SetSelfInfo(&BaseSuccessFailed{runFuncName(), operationID, wsRouter.uId}, userInfo, operationID)
这一行代码是该方法的核心部分,它实际上是调用了
userWorker
的User
方法(该方法可能返回用户相关的服务或操作接口)然后进一步调用了SetSelfInfo
方法来更新用户的个人信息。为
SetSelfInfo
方法传递了三个参数:- 一个是
BaseSuccessFailed
结构体的实例,这可能是一个用于回调的结构,其中包含了函数名、操作ID和用户ID。 userInfo
,这应该是一个字符串,表示要设置的用户信息。operationID
,这可能是一个操作或请求的唯一标识符,用于跟踪或日志记录。
- 一个是
SetSelfInfo
方法允许你为指定的用户设置其个人信息。在实际设置之前,它执行了一些前置检查以确保操作的有效性和安全性。
继续解析:
func runFuncName() string {
pc := make([]uintptr, 1)
runtime.Callers(2, pc)
f := runtime.FuncForPC(pc[0])
return f.Name()
}
这个函数 runFuncName
的目的是获取调用它的函数的名称。我们来逐步分析:
创建一个uintptr切片:
pc := make([]uintptr, 1)
这里创建了一个长度为1的
uintptr
切片,名为pc
。这个切片用来存储返回的程序计数器地址。获取调用者的信息:
runtime.Callers(2, pc)
Go的
runtime
包提供了Callers
函数,它返回调用它的函数的调用栈。第一个参数是返回的调用栈的“深度”。这里使用的值是2
,这意味着它会跳过runtime.Callers
和runFuncName
自身,来获得调用runFuncName
的函数的信息。返回的程序计数器地址存储在先前创建的
pc
切片中。从程序计数器获取函数信息:
f := runtime.FuncForPC(pc[0])
使用
runtime.FuncForPC
函数,我们可以获取给定程序计数器地址对应的函数的信息。因为我们只存储了一个地址在pc
切片中,所以我们使用pc[0]
。返回函数名称:
return f.Name()
最后,我们返回获取到的函数的名称。
我们再看看调用它的函数:
func (wsRouter *WsFuncRouter) checkResourceLoadingAndKeysIn(mgr *login.LoginMgr, input, operationID, funcName string, m map[string]interface{}, keys ...string) bool {
for _, k := range keys {
_, ok := m[k]
if !ok {
log.Info(operationID, "key not in", keys, input, operationID, funcName)
wsRouter.GlobalSendMessage(EventData{cleanUpfuncName(funcName), StatusBadParameter, "key not in", "", operationID})
return false
}
}
if err := open_im_sdk.CheckResourceLoad(mgr); err != nil {
log.Info(operationID, "Resource Loading ", mgr, err.Error())
wsRouter.GlobalSendMessage(EventData{cleanUpfuncName(funcName), StatusResourceNotCompleted, "resource loading is not completed", "", operationID})
return false
}
return true
}
这个函数 checkResourceLoadingAndKeysIn
似乎是一个预检查功能,确保资源加载并检查传入数据中是否存在必要的键。我们来详细分析每个部分:
函数参数:
mgr *login.LoginMgr
: 这是一个登录管理器,从结构上看,它可能用于管理各种与用户登录、消息和其他功能相关的资源。input string
: 可能是传入的数据或JSON字符串,用于检查是否包含所需的键。operationID string
: 用于在日志中识别特定的操作。funcName string
: 调用此检查功能的函数的名称。m map[string]interface{}
: 要检查键是否存在的映射。keys ...string
: 一个可变参数列表,列出要在映射中查找的键。
检查所有的键是否存在于映射中:
for _, k := range keys { _, ok := m[k] if !ok { ... return false } }
这个循环遍历每一个要求存在的键,检查它们是否真的存在于映射中。如果一个键不存在,它会记录一个日志消息并发送一个全局消息,然后返回
false
。检查资源是否已加载:
if err := open_im_sdk.CheckResourceLoad(mgr); err != nil { ... return false }
这部分使用
open_im_sdk.CheckResourceLoad
来检查相关的资源(可能是登录或其他相关资源)是否已经加载。如果资源未加载或有错误,它会记录日志并发送一个全局消息,然后返回false
。返回成功:
return true
如果所有的键都在映射中存在,并且所有资源都已加载,那么函数返回
true
表示检查成功。