你如何向V语言的结构体添加方法?

huangapple go评论58阅读模式
英文:

How can i add methods to a struct in vlang?

问题

我对V语言相当陌生,但我了解您的问题。您想在Error结构体中创建一个方法来返回包含所有值的字符串,以便可以调用它并将其存储在变量中。以下是您尝试的两种方法:

方法1:创建一个函数并返回字符串

fn to_string(e Error) string {
    return e.text + '\n in row ' + e.row.str() + ' at col ' + e.col.str() + '\n' + e.complementary
}

方法2:将方法附加到结构体(不起作用)

fn (e Error) to_string() string {
    return e.text + '\n in row ' + e.row.str() + ' at col ' + e.col.str() + '\n' + e.complementary
}

您想让第二种方法起作用,但它在编译时产生错误,错误消息是:

structs/error.v:11:7: error: cannot define new methods on non-local type Error

根据错误消息,似乎V语言不允许在非局部类型Error上定义新方法。要解决这个问题,您可以考虑将to_string函数保留为结构体的外部函数,就像您在方法1中所做的那样。这是一个修订后的示例:

module structs

pub struct Error {
    pub:
        text    string
        row    int
        col    int
        complementary    string
}

pub fn to_string(e Error) string {
    return e.text + '\n in row ' + e.row.str() + ' at col ' + e.col.str() + '\n' + e.complementary
}

然后,您可以在其他文件和模块中调用这个函数。

英文:

I am quite new to the v language and i discovered this feature, however it seems like i am doing something wrong.

I have a struct that gathers information in case an error is found somewhere and i'd like to create a function in the same structure to return a string containing all the values so that i can call it and store it in a variable the proper way: error_msg := error.to_string()

I am using v version 0.3.3

Having the Error struct:

pub struct Error {
    pub:
        text    string
        row    int
        col    int
        complementary    string
}

I have tried:

  • Creating a function and return it that way(This works but its not what i'd like)
fn to_string(e Error) string {
    return e.text+'\n in row '+ e.row+' at col '+ e.col+'\n'+e.complementary
}
  • Appending a method to the struct(Not working)
fn (e Error) to_string() string {
    return e.text+'\n in row '+ e.row+' at col '+ e.col+'\n'+e.complementary
}

I would like the second option to work but it is outputing the following error while compiling it:

structs/error.v:11:7: error: cannot define new methods on non-local type Error
    9 | }
   10 |
   11 | fn (e Error) to_string() string {
      |       ~~~~~
   12 |     return e.text+'\n in row '+ e.row+' at col '+ e.col+'\n'+e.complementary
   13 | }

The function and the struct are in the same module as expected and even in the same file
Full code

module structs

pub struct Error {
    pub:
        text    string
        row    int
        col    int
        complementary    string
}

fn (e Error) to_string() string {
    return e.text+'\n in row '+ e.row+' at col '+ e.col+'\n'+e.complementary
}

That being said, it is going to be called in another file and module:

pub fn read(file_name string) (int, string) {

    data := read_file(file_name) or {
        error_str := Error{text: 'File "$file_name" does not exist', row: 2, col: 0}
            return 1, error_str.to_string()
	}
	return 0, data
}

答案1

得分: 0

错误信息“无法在非本地类型Error上定义新方法”是因为Error是V内置的,因此已经在非本地定义了,您不能在此处添加新方法。

此外,您在方法定义上遇到此错误,可能是因为它在源代码中的结构定义之前。如果您交换它们的定义顺序(首先是结构,然后是方法),问题不会改变,但错误消息会更具针对性,会显示“无法注册结构Error,已存在具有此名称的另一种类型”。

快速修复

给您的struct一个新名称:

struct MyError {
  text             string
  row              int
  col              int
  complementary    string
}

fn (e MyError) to_string() string {
  return e.text + '在行' + e.row.str() + '列' + e.col.str() + '\n' + e.complementary
}

error_str := MyError{text: '文件不存在', row: 2, col: 0}
println(error_str.to_string())
文件不存在
在行2列0
更符合惯用法的方法

定义适当的自定义错误类型,然后可以将其用作实际错误:要么手动实现IError接口(需要两个方法msg() stringcode() int),要么只嵌入接口的默认实现Error(是的,您不小心尝试隐藏的那个),它提供了这两个方法的空副本,因此您只需添加需要的内容。例如:

struct MyError {
  Error
  text             string
  row              int
  col              int
  complementary    string
}

fn (e MyError) msg() string {
  return '${e.text}\n在行${e.row}${e.col}\n${e.complementary}'
}

fn read(file_name string) !string {
  failed := true
  if failed {
    return MyError{text: '文件"${file_name}"不存在', row: 2, col: 0}
  }
  return "数据"
}

data := read("xy") or { panic(err) }
println(data)
V panic: MyError: 文件"xy"不存在
在行2列0

v hash: 046dd54
/tmp/v_1000/main.13380111000873620315.tmp.c:7817: 在 _v_panic 中的回溯
/tmp/v_1000/main.13380111000873620315.tmp.c:17765: 由 main__main
/tmp/v_1000/main.13380111000873620315.tmp.c:18160: 由 main
英文:

The error cannot define new methods on non-local type Error occurs because Error is a V builtin, thus already defined (non-locally), and you cannot add a new method to that here.

Also, you're getting this error on the method definition because it presumably precedes the struct's definition in your source code. If you flipped their order of definition (struct first, then the method), the issue wouldn't change but the error message would have been more to the point, reading: cannot register struct `Error`, another type with this name exists.

The quick fix

Give your struct a new name:

struct MyError {
  text             string
  row              int
  col              int
  complementary    string
}

fn (e MyError) to_string() string {
  return e.text + '\n in row ' + e.row.str() + ' at col ' + e.col.str() + '\n' + e.complementary
}

error_str := MyError{text: 'File does not exist', row: 2, col: 0}
println(error_str.to_string())
File does not exist
 in row 2 at col 0
A more idiomatic approach

Define proper custom error types which you can then use as actual errors: Either manually implement the IError interface (requiring the two methods msg() string and code() int), or just embed the interface's default implementation Error (yes, the one you have accidentally been trying to shadow) which provides empty copies of both methods, so you only have to add what's needed. For instance:

struct MyError {
  Error
  text             string
  row              int
  col              int
  complementary    string
}

fn (e MyError) msg() string {
  return '${e.text}\n in row ${e.row} at col ${e.col}\n${e.complementary}'
}

fn read(file_name string) !string {
  failed := true
  if failed {
    return MyError{text: 'File "${file_name}" does not exist', row: 2, col: 0}
  }
  return "data"
}

data := read("xy") or { panic(err) }
println(data)
V panic: MyError: File "xy" does not exist
 in row 2 at col 0

v hash: 046dd54
/tmp/v_1000/main.13380111000873620315.tmp.c:7817: at _v_panic: Backtrace
/tmp/v_1000/main.13380111000873620315.tmp.c:17765: by main__main
/tmp/v_1000/main.13380111000873620315.tmp.c:18160: by main

huangapple
  • 本文由 发表于 2023年7月4日 21:37:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/76613215.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定