Golang新手求助:寻找解决方案

Golang新手求助:寻找解决方案 请查看这段代码,我在 db_service.go 文件中为登录功能编写的 Find_User 函数。它本应查询用户的邮箱和密码,但没有返回任何结果,而是返回了空结果。我使用的是 mux 和 MongoDB。

func Find_User(user *model.User) (*mongo.ListDatabasesResult, error) {
	//Create a handle to the respective collection in the database.
	obejctId, err := primitive.ObjectIDFromHex(user.Email)
	if err != nil {
		return nil, err
	}
	result := clientInstance.Database(AUTH_DB).Collection(USER_COLLECTION).FindOne(context.Background(), bson.M{"_id": obejctId})

	result.Decode(&user)
	return nil, nil

}

以下是按部分划分的完整代码

db_service.go

/* Used to create a singleton object of MongoDB client.
Initialized and exposed through  GetMongoClient().*/
var clientInstance *mongo.Client

//Used during creation of singleton client object in GetMongoClient().
var clientInstanceError error

//Used to execute client creation procedure only once.
var mongoOnce sync.Once

//I have used below constants just to hold required database config's.
const (
	CONNECTIONSTRING = "http://127.0.0.1:27017"
	AUTH_DB          = "Cluster0"
	USER_COLLECTION  = "user"
)

//GetMongoClient - Return mongodb connection to work with
func GetMongoClient() (*mongo.Client, error) {

	//Perform connection creation operation only once.
	mongoOnce.Do(func() {
		// Set client options
		clientOptions := options.Client().ApplyURI(CONNECTIONSTRING)
		// Connect to MongoDB
		client, err := mongo.Connect(context.TODO(), clientOptions)
		if err != nil {
			clientInstanceError = err
		}
		// Check the connection
		err = client.Ping(context.TODO(), nil)
		if err != nil {
			clientInstanceError = err
		}
		log.Println("Connected Mongodb!")
		clientInstance = client
	})

	return clientInstance, clientInstanceError
}

//CreateIssue - Insert a new document in the collection.
func User_Collection(user *model.User) (*mongo.InsertOneResult, error) {

	//Create a handle to the respective collection in the database.
	collection := clientInstance.Database(AUTH_DB).Collection(USER_COLLECTION)

	//Perform InsertOne operation & validate against the error.
	return collection.InsertOne(context.TODO(), user)
}
func Find_User(user *model.User) (*mongo.ListDatabasesResult, error) {
	//Create a handle to the respective collection in the database.
	obejctId, err := primitive.ObjectIDFromHex(user.Email)
	if err != nil {
		return nil, err
	}
	result := clientInstance.Database(AUTH_DB).Collection(USER_COLLECTION).FindOne(context.Background(), bson.M{"_id": obejctId})

	result.Decode(&user)
	return nil, nil

}

login_service.go

func Register_User(user *model.User) (interface{}, error) {

	user.CreatedAt = time.Now().UTC()
	user.UpdatedAt = time.Now().UTC()
	if result, err := util.User_Collection(user); err == nil {
		return result.InsertedID, err
	} else {
		return nil, err
	}
}

func Login_User(user *model.User) (interface{}, error) {

	if result, err := util.Find_User(user); err == nil {
		return result, err
	} else {
		return nil, err
	}
}

login.go

func Register(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")

	var user model.User
	if err := json.NewDecoder(r.Body).Decode(&user); err == nil {

		if _, err := service.Register_User(&user); err == nil {
			w.WriteHeader(http.StatusCreated)
			json.NewEncoder(w).Encode(user)
		} else {
			w.WriteHeader(http.StatusInternalServerError)
			json.NewEncoder(w).Encode(err)
		}

	} else {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

}
func Login(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	var user model.User
	if err := json.NewDecoder(r.Body).Decode(&user); err == nil {
		if _, err := service.Login_User(&user); err == nil {
			json.NewEncoder(w).Encode(user)
		} else {
			w.WriteHeader(http.StatusInternalServerError)
			json.NewEncoder(w).Encode(err)
		}
	} else {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
}

请帮帮我。


更多关于Golang新手求助:寻找解决方案的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

你好,

Find_User() 函数在成功时显然不返回任何内容,而是更新 user 参数。

result.Decode(&user)
return nil, nil

这相当不寻常,但无论如何……

我的第一个问题是,“返回空白结果”具体是什么意思?

  • user 是空的吗?
  • 如果是,result 是否包含你期望的数据?
  • result.Decode() 是否会返回一个你可以检查的错误?

也许你可以添加一些代码来在 resultuser 被填充后转储它们的内容,例如:

result := clientInstance.Database(AUTH_DB).Collection(USER_COLLECTION).FindOne(context.Background(), bson.M{"_id": obejctId})
log.Printf("%v\n", result)
result.Decode(&user)
log.Printf("%v\n", user)

另外,我希望可以评论一下我注意到的两点:

  • 如果你不打算使用返回值,直接省略它。return nil, nil 看起来相当不寻常。
  • 按照惯例,Go 中的名称不应包含下划线。
  • 提示:减少缩进代码量,当函数最后一条语句无论如何都是 return 时,可以移除 else 分支,例如:
    if err != nil {
        return err 
    }
    return nil
    
    代码越靠左对齐,就越容易阅读。

更多关于Golang新手求助:寻找解决方案的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


你的代码有几个关键问题需要修复:

主要问题:

  1. 函数签名错误Find_User 返回了错误的类型 *mongo.ListDatabasesResult
  2. 查询逻辑错误:使用邮箱作为 _id 进行查询,但 _id 应该是 ObjectID
  3. 错误处理不完整:没有正确处理 FindOne 的错误

修正后的代码:

db_service.go 中的 Find_User 函数:

func Find_User(user *model.User) (*model.User, error) {
    // 根据邮箱查询用户,而不是使用邮箱作为 _id
    filter := bson.M{"email": user.Email}
    
    // 执行查询
    result := clientInstance.Database(AUTH_DB).Collection(USER_COLLECTION).
        FindOne(context.Background(), filter)
    
    // 检查查询错误
    if err := result.Err(); err != nil {
        if err == mongo.ErrNoDocuments {
            return nil, fmt.Errorf("用户不存在")
        }
        return nil, err
    }
    
    // 解码结果到 user 对象
    if err := result.Decode(user); err != nil {
        return nil, err
    }
    
    return user, nil
}

login_service.go 中的 Login_User 函数需要相应调整:

func Login_User(user *model.User) (interface{}, error) {
    // 先根据邮箱查找用户
    foundUser, err := util.Find_User(user)
    if err != nil {
        return nil, err
    }
    
    // 验证密码(假设你的 User 模型有 Password 字段)
    if foundUser.Password != user.Password {
        return nil, fmt.Errorf("密码错误")
    }
    
    return foundUser, nil
}

额外建议:

  1. 修复连接字符串
const (
    CONNECTIONSTRING = "mongodb://127.0.0.1:27017"  // 应该是 mongodb:// 而不是 http://
)
  1. 确保 User 模型正确
type User struct {
    ID        primitive.ObjectID `bson:"_id,omitempty" json:"id,omitempty"`
    Email     string             `bson:"email" json:"email"`
    Password  string             `bson:"password" json:"password"`
    CreatedAt time.Time          `bson:"created_at" json:"created_at"`
    UpdatedAt time.Time          `bson:"updated_at" json:"updated_at"`
}
  1. 添加密码哈希功能(安全考虑):
import "golang.org/x/crypto/bcrypt"

func HashPassword(password string) (string, error) {
    bytes, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
    return string(bytes), err
}

func CheckPasswordHash(password, hash string) bool {
    err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
    return err == nil
}

主要问题是你在尝试使用邮箱字符串作为 ObjectID 来查询,而 MongoDB 的 _id 字段通常是自动生成的 ObjectID。你应该使用邮箱作为查询条件来查找用户。

回到顶部