You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ballerina:隔离函数中无法访问只读类属性的问题及解决方法

关于Ballerina中readonly类self实例被判定可变的编译错误问题

我定义了两个相互关联的服务类Astronaut和Mission,并尝试将它们设置为isolated(隔离)状态,但出现了编译错误:

invalid access of mutable storage in an 'isolated' function

我的疑问:readonly class Astronaut的self实例为何会被判定为可变?针对该情况是否有可行的解决方法?

以下是我的代码:

distinct isolated service readonly class Mission {
    public final int id;
    private final string designation;
    private final string? startDate;
    private final string? endDate;
    private final readonly & int[] crewIds;

    isolated function init(int id, string designation, string? startDate, string? endDate, readonly & int[] crewIds) {
        self.id = id;
        self.designation = designation;
        self.startDate = startDate;
        self.endDate = endDate;
        self.crewIds = crewIds;
    }

    isolated resource function get id() returns int {
        return self.id;
    }

    isolated resource function get designation() returns string {
        return self.designation;
    }

    isolated resource function get startDate() returns string? {
        return self.startDate;
    }

    isolated resource function get endDate() returns string? {
        return self.endDate;
    }

    isolated resource function get crew() returns Astronaut[] {
        return self.crewIds.map(isolated function(int id) returns Astronaut {
            return new (id);
        });
    }

    public isolated function includes(int id) returns boolean {
        return self.crewIds.indexOf(id) != ();
    }

}

distinct isolated service readonly class Astronaut {
    private final int id;
    isolated function init(int id) {
        self.id = id;
    }

    isolated resource function get id() returns int {
        return self.id;
    }

    isolated resource function get missions() returns Mission[] {
        return missions.filter(isolated function(Mission mission) returns boolean {
            return mission.includes(self.id); // <=============== 引发编译错误的行
        });
    }
}

final readonly & Mission[] missions = [
    new Mission(1, "Apollo 1", (), (), [14, 30, 7]),
    new Mission(2, "Apollo 4", "1967-11-09T12:00:01.000Z", "1967-11-09T20:37:00.000Z", [])
];

问题原因

Ballerina的isolated函数对捕获的变量有严格要求:必须是不可变且可安全共享的。虽然Astronaut是readonly类,但self作为实例的引用本身,在isolated lambda函数中被捕获时,编译器无法静态保证这个引用不会被其他并发操作修改——即使类的字段都是不可变的,引用本身的可变性依然会被编译器纳入检查范围,因此self被判定为"可变存储",违反了isolated函数的规则。

解决方法

方案:提取不可变字段到局部final变量

将self.id提取到一个局部的final变量中,这个变量是完全不可变的,符合isolated lambda对捕获变量的要求,你已经采用了这个正确的解决方式:

isolated resource function get missions() returns Mission[] {
    final int id = self.id;
    return missions.filter(isolated function(Mission mission) returns boolean {
        return mission.includes(id);
    });
}

这种方式的核心是把需要在lambda中使用的不可变值从self实例中剥离出来,转换成一个孤立的不可变变量,让编译器明确确认该变量不会被并发修改,从而通过isolated函数的合规性检查。

内容的提问来源于stack exchange,提问作者Mohamed Ishad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 03:49:56